

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
  <link rel="icon" href="/img/fluid.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="c5p1ng">
  <meta name="keywords" content="">
  
    <meta name="description" content="DevOps一、DevOps介绍软件开发最开始是由两个团队组成：  开发计划由开发团队从头开始设计和整体系统的构建。需要系统不停的迭代更新。 运维团队将开发团队的Code进行测试后部署上线。希望系统稳定安全运行。  这看似两个目标不同的团队需要协同完成一个软件的开发。 在开发团队指定好计划并完成coding后，需要提供到运维团队。 运维团队向开发团队反馈需要修复的BUG以及一些需要返工的任务。 这">
<meta property="og:type" content="article">
<meta property="og:title" content="DevOps">
<meta property="og:url" content="http://example.com/2023/06/11/DevOps/index.html">
<meta property="og:site_name" content="c5p1ng个人博客">
<meta property="og:description" content="DevOps一、DevOps介绍软件开发最开始是由两个团队组成：  开发计划由开发团队从头开始设计和整体系统的构建。需要系统不停的迭代更新。 运维团队将开发团队的Code进行测试后部署上线。希望系统稳定安全运行。  这看似两个目标不同的团队需要协同完成一个软件的开发。 在开发团队指定好计划并完成coding后，需要提供到运维团队。 运维团队向开发团队反馈需要修复的BUG以及一些需要返工的任务。 这">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124130409521.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/2021-11-23_175935.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124182140596.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124182921234.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124183003858.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124193444561.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124200317795.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124200658107.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125141950900.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125141701495.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125154112097.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124202610243.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124204517433.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124203336300.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124205050484.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124205513465.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124205854418.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124205858730.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124205917317.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124211635550.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124211700999.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211124211720836.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125195818670.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125163541645.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125170350811.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125170418337.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125200218093.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125201701443.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125201919108.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125203757232.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125204811759.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125204818869.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125205027013.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125205020738.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125205240208.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125205725948.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125210148202.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125205027013.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125210424346.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125210626631.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125210755556.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211125210826057.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126161304485.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126161331991.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126161408514.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126161448527.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126161504715.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126161509411.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126165209057.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126165444124.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126172828266.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126165639286.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126174715028.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211126174159487.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129190039986.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211207145215817.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211207145342350.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129191426344.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129191537050.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129193824428.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129194148239.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129194621820.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129194748765.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129194931944.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129195430146.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129195503762.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130140043382.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130141303457.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130144608025.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129201625561.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129201607240.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129202147390.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130144850186.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129203102334.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129203235019.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129203342171.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211129203457604.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130153628925.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130155849143.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130160017465.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130160047648.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130215555218.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130215941857.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130220028840.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211130220111602.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201213427157.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201213751780.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201213832458.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201214008303.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201221040200.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201215931237.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201221225196.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201221300055.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211201222450091.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211229155834500.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202145155428.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202145240166.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202145349043.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202151127254.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202151155145.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202151225161.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202191944277.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211202192047619.png">
<meta property="og:image" content="c:\Users\Administrator\Desktop\DevOps%E7%AC%94%E8%AE%B0-MarkDown%E5%8E%9F%E7%89%88\DevOps\Pictures\image-20211202192129895.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211209151549412.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211209152217433.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211209152252050.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211209152403312.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211209162923440.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211209163021396.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211210114507638.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211210190653687.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211213183025291.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211210184851810.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211213184701784.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211213184742709.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20211213184840120.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220104203155749.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220104210823057.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220104214659229.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220104215030265.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220104222750733.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220104222819455.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105205334996.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105153343642.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105153416367.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105153502619.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105203819715.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105204434044.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105204921272.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/image-20220105205407393.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642498962716.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642498994935.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642499172789.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642499368121.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642499788199.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642499885324.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642499992148.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500061153.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500102996.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500239406.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500378788.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500413802.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500474036.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500817131.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642500933316.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642501016474.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642501065243.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642501521065.png">
<meta property="og:image" content="http://example.com/images/DevOps/Pictures/1642501549176.png">
<meta property="article:published_time" content="2023-06-11T02:09:48.000Z">
<meta property="article:modified_time" content="2023-06-11T06:20:48.916Z">
<meta property="article:author" content="c5p1ng">
<meta property="article:tag" content="devops">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://example.com/images/DevOps/Pictures/image-20211124130409521.png">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>DevOps - c5p1ng个人博客</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.9.4","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.3.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Fluid</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="DevOps"></span>
          
        </div>

        
          
  <div class="mt-3">
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2023-06-11 10:09" pubdate>
          2023年6月11日 上午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          37k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          306 分钟
        
      </span>
    

    
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">DevOps</h1>
            
            
              <div class="markdown-body">
                
                <h1 id="DevOps"><a href="#DevOps" class="headerlink" title="DevOps"></a>DevOps</h1><h3 id="一、DevOps介绍"><a href="#一、DevOps介绍" class="headerlink" title="一、DevOps介绍"></a>一、DevOps介绍</h3><p>软件开发最开始是由两个团队组成：</p>
<ul>
<li>开发计划由<a href="">开发团队</a>从头开始设计和整体系统的构建。需要系统不停的迭代更新。</li>
<li><a href="">运维团队</a>将开发团队的Code进行测试后部署上线。希望系统稳定安全运行。</li>
</ul>
<p>这看似两个目标不同的团队需要协同完成一个软件的开发。</p>
<p>在开发团队指定好计划并完成coding后，需要提供到运维团队。</p>
<p>运维团队向开发团队反馈需要修复的BUG以及一些需要返工的任务。</p>
<p>这时开发团队需要经常等待运维团队的反馈。这无疑延长了事件并推迟了整个软件开发的周期。</p>
<p>会有一种方式，在开发团队等待的时候，让开发团队转移到下一个项目中。等待运维团队为之前的代码提供反馈。</p>
<p>可是这样就意味着一个完整的项目需要一个更长的周期才可以开发出最终代码。</p>
<hr>
<p>基于现在的互联网现状，更推崇敏捷式开发，这样就导致项目的迭代速度更快，但是由于开发团队与运维团队的沟通问题，会导致新版本上线的时间成本很高。这又违背的敏捷式开发的最初的目的。</p>
<p>那么如果让开发团队和运维团队整合到成一个团队，协同应对一套软件呢？这就被称为<a href="">DevOps</a>。</p>
<p><a href="">DevOps</a>，字面意思是Development &amp;Operations的缩写，也就是开发&amp;运维。</p>
<p>虽然字面意思只涉及到了开发团队和运维团队，其实QA测试团队也是参与其中的。</p>
<p>网上可以查看到<a href="">DevOps</a>的符号类似于一个无穷大的符号</p>
<table>
<thead>
<tr>
<th align="center"><a href="">DevOps</a></th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124130409521.png" srcset="/img/loading.gif" lazyload alt="image-20211124130409521"></td>
</tr>
</tbody></table>
<p>这表明<a href="">DevOps</a>是一个不断提高效率并且持续不断工作的过程</p>
<p><a href="">DevOps</a>的方式可以让公司能够更快地应对更新和市场发展变化，开发可以快速交付，部署也更加稳定。</p>
<p>核心就在于<a href="">简化Dev和Ops团队之间的流程，使整体软件开发过程更快速。</a></p>
<p>整体的软件开发流程包括：</p>
<ul>
<li>PLAN：开发团队根据客户的目标制定开发计划</li>
<li>CODE：根据PLAN开始编码过程，需要将不同版本的代码存储在一个库中。</li>
<li>BUILD：编码完成后，需要将代码构建并且运行。</li>
<li>TEST：成功构建项目后，需要测试代码是否存在BUG或错误。</li>
<li>DEPLOY：代码经过手动测试和自动化测试后，认定代码已经准备好部署并且交给运维团队。</li>
<li>OPERATE：运维团队将代码部署到生产环境中。</li>
<li>MONITOR：项目部署上线后，需要持续的监控产品。</li>
<li>INTEGRATE：然后将监控阶段收到的反馈发送回PLAN阶段，整体反复的流程就是<a href="">DevOps</a>的核心，即持续集成、持续部署。</li>
</ul>
<p>为了保证整体流程可以高效的完成，各个阶段都有比较常见的工具，如下图：</p>
<table>
<thead>
<tr>
<th align="center">软件开发过程&amp;涉及工具</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/2021-11-23_175935.png" srcset="/img/loading.gif" lazyload alt="2021-11-23_175935"></td>
</tr>
</tbody></table>
<p>最终可以给<a href="">DevOps</a>下一个定义：<a href="">DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理，从而更快、更频繁地交付更稳定的软件。</a></p>
<p>自动化的工具协作和沟通来完成软件的生命周期管理</p>
<h3 id="二、Code阶段工具"><a href="#二、Code阶段工具" class="headerlink" title="二、Code阶段工具"></a>二、Code阶段工具</h3><p>在code阶段，我们需要将不同版本的代码存储到一个仓库中，常见的版本控制工具就是SVN或者Git，这里我们采用Git作为版本控制工具，GitLab作为远程仓库。</p>
<h4 id="2-1-Git安装"><a href="#2-1-Git安装" class="headerlink" title="2.1 Git安装"></a>2.1 Git安装</h4><p><a target="_blank" rel="noopener" href="https://git-scm.com/%EF%BC%88%E5%82%BB%E7%93%9C%E5%BC%8F%E5%AE%89%E8%A3%85%EF%BC%89">https://git-scm.com/（傻瓜式安装）</a></p>
<h4 id="2-2-GitLab安装"><a href="#2-2-GitLab安装" class="headerlink" title="2.2 GitLab安装"></a>2.2 GitLab安装</h4><p>单独准备服务器，采用Docker安装</p>
<ul>
<li><p>查看GitLab镜像</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker search gitlab<br></code></pre></td></tr></table></figure>
</li>
<li><p>拉取GitLab镜像</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker pull gitlab/gitlab-ce<br></code></pre></td></tr></table></figure>
</li>
<li><p>准备docker-compose.yml文件</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">version:</span> <span class="hljs-string">&#x27;3.1&#x27;</span><br><span class="hljs-attr">services:</span><br>  <span class="hljs-attr">gitlab:</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">&#x27;gitlab/gitlab-ce:latest&#x27;</span><br>    <span class="hljs-attr">container_name:</span> <span class="hljs-string">gitlab</span><br>    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span><br>    <span class="hljs-attr">environment:</span><br>      <span class="hljs-attr">GITLAB_OMNIBUS_CONFIG:</span> <span class="hljs-string">|</span><br><span class="hljs-string">        external_url &#x27;http://192.168.11.11:8929&#x27;</span><br><span class="hljs-string">        gitlab_rails[&#x27;gitlab_shell_ssh_port&#x27;] = 2224</span><br><span class="hljs-string"></span>    <span class="hljs-attr">ports:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&#x27;8929:8929&#x27;</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&#x27;2224:2224&#x27;</span><br>    <span class="hljs-attr">volumes:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&#x27;./config:/etc/gitlab&#x27;</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&#x27;./logs:/var/log/gitlab&#x27;</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&#x27;./data:/var/opt/gitlab&#x27;</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>启动容器（需要稍等一小会……）</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker-compose up -d<br></code></pre></td></tr></table></figure>
</li>
<li><p>访问GitLab首页</p>
<table>
<thead>
<tr>
<th align="center">首页</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124182140596.png" srcset="/img/loading.gif" lazyload alt="image-20211124182140596"></td>
</tr>
</tbody></table>
</li>
<li><p>查看root用户初始密码</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker <span class="hljs-built_in">exec</span> -it gitlab <span class="hljs-built_in">cat</span> /etc/gitlab/initial_root_password<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">初始密码</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124182921234.png" srcset="/img/loading.gif" lazyload alt="image-20211124182921234"></td>
</tr>
</tbody></table>
</li>
<li><p>登录root用户</p>
<table>
<thead>
<tr>
<th align="center">登录成功后跳转页面</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124183003858.png" srcset="/img/loading.gif" lazyload alt="image-20211124183003858"></td>
</tr>
</tbody></table>
</li>
<li><p>第一次登录后需要修改密码</p>
<table>
<thead>
<tr>
<th align="center">修改密码</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124193444561.png" srcset="/img/loading.gif" lazyload alt="image-20211124193444561"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>搞定后，即可像Gitee、GitHub一样使用。</p>
<h3 id="三、Build阶段工具"><a href="#三、Build阶段工具" class="headerlink" title="三、Build阶段工具"></a>三、Build阶段工具</h3><p>构建Java项目的工具一般有两种选择，一个是Maven，一个是Gradle。</p>
<p>这里我们选择Maven作为项目的编译工具。</p>
<p>具体安装Maven流程不做阐述，但是需要确保配置好Maven仓库私服以及JDK编译版本。</p>
<h3 id="四、Operate阶段工具"><a href="#四、Operate阶段工具" class="headerlink" title="四、Operate阶段工具"></a>四、Operate阶段工具</h3><p>部署过程，会采用Docker进行部署，暂时只安装Docker即可，后续还需安装Kubenetes</p>
<h4 id="4-1-Docker安装"><a href="#4-1-Docker安装" class="headerlink" title="4.1 Docker安装"></a>4.1 Docker安装</h4><ul>
<li><p>准备测试环境&amp;生产环境</p>
</li>
<li><p>下载Docker依赖组件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">yum -y install yum-utils device-mapper-persistent-data lvm2<br></code></pre></td></tr></table></figure>
</li>
<li><p>设置下载Docker的镜像源为阿里云</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo<br></code></pre></td></tr></table></figure>
</li>
<li><p>安装Docker服务</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">yum -y install docker-ce<br></code></pre></td></tr></table></figure>
</li>
<li><p>安装成功后，启动Docker并设置开机自启</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 启动Docker服务</span><br>systemctl start docker<br><span class="hljs-comment"># 设置开机自动启动</span><br>systemctl <span class="hljs-built_in">enable</span> docker<br></code></pre></td></tr></table></figure>
</li>
<li><p>测试安装成功</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker version<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124200317795.png" srcset="/img/loading.gif" lazyload alt="image-20211124200317795"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="4-2-Docker-Compose安装"><a href="#4-2-Docker-Compose安装" class="headerlink" title="4.2 Docker-Compose安装"></a>4.2 Docker-Compose安装</h4><ul>
<li><p>下载Docker&#x2F;Compose：<a target="_blank" rel="noopener" href="https://github.com/docker/compose">https://github.com/docker/compose</a></p>
</li>
<li><p>将下载好的<a href="">docker-compose-Linux-x86_64</a>文件移动到Linux操作系统：……</p>
</li>
<li><p>设置<a href="">docker-compose-Linux-x86_64</a>文件权限，并移动到$PATH目录中</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 设置文件权限</span><br><span class="hljs-built_in">chmod</span> a+x docker-compose-Linux-x86_64<br><span class="hljs-comment"># 移动到/usr/bin目录下，并重命名为docker-compose</span><br><span class="hljs-built_in">mv</span> docker-compose-Linux-x86_64 /usr/bin/docker-compose<br></code></pre></td></tr></table></figure>
</li>
<li><p>测试安装成功</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker-compose version<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124200658107.png" srcset="/img/loading.gif" lazyload alt="image-20211124200658107"></td>
</tr>
</tbody></table>
</li>
</ul>
<h3 id="五、Integrate工具"><a href="#五、Integrate工具" class="headerlink" title="五、Integrate工具"></a>五、Integrate工具</h3><p>持续集成、持续部署的工具很多，其中Jenkins是一个开源的持续集成平台。</p>
<p>Jenkins涉及到将编写完毕的代码发布到测试环境和生产环境的任务，并且还涉及到了构建项目等任务。</p>
<p>Jenkins需要大量的插件保证工作，安装成本较高，下面会基于Docker搭建Jenkins。</p>
<h4 id="5-1-Jenkins介绍"><a href="#5-1-Jenkins介绍" class="headerlink" title="5.1 Jenkins介绍"></a>5.1 Jenkins介绍</h4><p>Jenkins是一个开源软件项目，是基于Java开发的一种持续集成工具</p>
<p>Jenkins应用广泛，大多数互联网公司都采用Jenkins配合GitLab、Docker、K8s作为实现<a href="">DevOps</a>的核心工具。</p>
<p>Jenkins最强大的就在于插件，Jenkins官方提供了大量的插件库，来自动化CI&#x2F;CD过程中的各种琐碎功能。</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center"></th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125141950900.png" srcset="/img/loading.gif" lazyload alt="image-20211125141950900"></td>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125141701495.png" srcset="/img/loading.gif" lazyload alt="image-20211124200317795"></td>
</tr>
</tbody></table>
<p>Jenkins最主要的工作就是将GitLab上可以构建的工程代码拉取并且进行构建，再根据流程可以选择发布到测试环境或是生产环境。</p>
<p>一般是GitLab上的代码经过大量的测试后，确定发行版本，再发布到生产环境。</p>
<p>CI&#x2F;CD可以理解为：</p>
<ul>
<li>CI过程即是通过Jenkins将代码拉取、构建、制作镜像交给测试人员测试。<ul>
<li>持续集成：让软件代码可以持续的集成到主干上，并自动构建和测试。</li>
</ul>
</li>
<li>CD过程即是通过Jenkins将打好标签的发行版本代码拉取、构建、制作镜像交给运维人员部署。<ul>
<li>持续交付：让经过持续集成的代码可以进行手动部署。</li>
<li>持续部署：让可以持续交付的代码随时随地的自动化部署。</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th align="center">CI、CD</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125154112097.png" srcset="/img/loading.gif" lazyload alt="image-20211125154112097"></td>
</tr>
</tbody></table>
<h4 id="5-2-Jenkins安装"><a href="#5-2-Jenkins安装" class="headerlink" title="5.2 Jenkins安装"></a>5.2 Jenkins安装</h4><ul>
<li><p>拉取Jenkins镜像</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker pull jenkins/jenkins<br></code></pre></td></tr></table></figure>
</li>
<li><p>编写docker-compose.yml</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">version:</span> <span class="hljs-string">&quot;3.1&quot;</span><br><span class="hljs-attr">services:</span><br>  <span class="hljs-attr">jenkins:</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">jenkins/jenkins</span><br>    <span class="hljs-attr">container_name:</span> <span class="hljs-string">jenkins</span><br>    <span class="hljs-attr">ports:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-number">8080</span><span class="hljs-string">:8080</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-number">50000</span><span class="hljs-string">:50000</span><br>    <span class="hljs-attr">volumes:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">./data/:/var/jenkins_home/</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>首次启动会因为数据卷data目录没有权限导致启动失败，设置data目录写权限</p>
<table>
<thead>
<tr>
<th align="center">错误日志</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124202610243.png" srcset="/img/loading.gif" lazyload alt="image-20211124202610243"></td>
</tr>
</tbody></table>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-built_in">chmod</span> -R a+w data/<br></code></pre></td></tr></table></figure>
</li>
<li><p>重新启动Jenkins容器后，由于Jenkins需要下载大量内容，但是由于默认下载地址下载速度较慢，需要重新设置下载地址为国内镜像站</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 修改数据卷中的hudson.model.UpdateCenter.xml文件</span><br>&lt;?xml version=<span class="hljs-string">&#x27;1.1&#x27;</span> encoding=<span class="hljs-string">&#x27;UTF-8&#x27;</span>?&gt;<br>&lt;sites&gt;<br>  &lt;site&gt;<br>    &lt;<span class="hljs-built_in">id</span>&gt;default&lt;/id&gt;<br>    &lt;url&gt;https://updates.jenkins.io/update-center.json&lt;/url&gt;<br>  &lt;/site&gt;<br>&lt;/sites&gt;<br><span class="hljs-comment"># 将下载地址替换为http://mirror.esuni.jp/jenkins/updates/update-center.json</span><br>&lt;?xml version=<span class="hljs-string">&#x27;1.1&#x27;</span> encoding=<span class="hljs-string">&#x27;UTF-8&#x27;</span>?&gt;<br>&lt;sites&gt;<br>  &lt;site&gt;<br>    &lt;<span class="hljs-built_in">id</span>&gt;default&lt;/id&gt;<br>    &lt;url&gt;http://mirror.esuni.jp/jenkins/updates/update-center.json&lt;/url&gt;<br>  &lt;/site&gt;<br>&lt;/sites&gt;<br><span class="hljs-comment"># 清华大学的插件源也可以https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>再次重启Jenkins容器，访问Jenkins（需要稍微等会）</p>
<table>
<thead>
<tr>
<th align="center">Jenkins首页</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124204517433.png" srcset="/img/loading.gif" lazyload alt="image-20211124204517433"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124203336300.png" srcset="/img/loading.gif" lazyload alt="image-20211124203336300"></td>
</tr>
</tbody></table>
</li>
<li><p>查看密码登录Jenkins，并登录下载插件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker <span class="hljs-built_in">exec</span> -it jenkins <span class="hljs-built_in">cat</span> /var/jenkins_home/secrets/initialAdminPassword<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">登录并下载插件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124205050484.png" srcset="/img/loading.gif" lazyload alt="image-20211124205050484"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124205513465.png" srcset="/img/loading.gif" lazyload alt="image-20211124205513465"></td>
</tr>
</tbody></table>
</li>
<li><p>选择需要安装的插件</p>
<table>
<thead>
<tr>
<th align="center">选择需要安装的插件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124205854418.png" srcset="/img/loading.gif" lazyload alt="image-20211124205854418"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124205858730.png" srcset="/img/loading.gif" lazyload alt="image-20211124205858730"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211124205917317.png" srcset="/img/loading.gif" lazyload alt="image-20211124205917317"></td>
</tr>
</tbody></table>
</li>
<li><p>下载完毕设置信息进入首页（可能会出现下载失败的插件）</p>
<table>
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody><tr>
<td><img src="/../images/DevOps/Pictures/image-20211124211635550.png" srcset="/img/loading.gif" lazyload alt="image-20211124211635550"></td>
</tr>
<tr>
<td><img src="/../images/DevOps/Pictures/image-20211124211700999.png" srcset="/img/loading.gif" lazyload alt="image-20211124211700999"></td>
</tr>
<tr>
<td><img src="/../images/DevOps/Pictures/image-20211124211720836.png" srcset="/img/loading.gif" lazyload alt="image-20211124211720836"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="5-3-Jenkins入门配置"><a href="#5-3-Jenkins入门配置" class="headerlink" title="5.3 Jenkins入门配置"></a>5.3 Jenkins入门配置</h4><p>由于Jenkins需要从Git拉取代码、需要本地构建、甚至需要直接发布自定义镜像到Docker仓库，所以Jenkins需要配置大量内容。</p>
<h5 id="5-3-1-构建任务"><a href="#5-3-1-构建任务" class="headerlink" title="5.3.1 构建任务"></a>5.3.1 构建任务</h5><p>准备好GitLab仓库中的项目，并且通过Jenkins配置项目的实现当前项目的<a href="">DevOps</a>基本流程。</p>
<ul>
<li><p>构建Maven工程发布到GitLab（Gitee、Github均可）</p>
<table>
<thead>
<tr>
<th align="center">GitLab查看项目</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125195818670.png" srcset="/img/loading.gif" lazyload alt="image-20211125195818670"></td>
</tr>
</tbody></table>
</li>
<li><p>Jenkins点击左侧导航新建任务</p>
<table>
<thead>
<tr>
<th align="center">新建任务</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125163541645.png" srcset="/img/loading.gif" lazyload alt="image-20211125163541645"></td>
</tr>
</tbody></table>
</li>
<li><p>选择自由风格构建任务</p>
<table>
<thead>
<tr>
<th align="center">构建任务</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125170350811.png" srcset="/img/loading.gif" lazyload alt="image-20211125170350811"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="5-3-1-配置源码拉取地址"><a href="#5-3-1-配置源码拉取地址" class="headerlink" title="5.3.1 配置源码拉取地址"></a>5.3.1 配置源码拉取地址</h5><p>Jenkins需要将Git上存放的源码存储到Jenkins服务所在磁盘的本地</p>
<ul>
<li><p>配置任务源码拉取的地址</p>
<table>
<thead>
<tr>
<th align="center">源码管理</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125170418337.png" srcset="/img/loading.gif" lazyload alt="image-20211125170418337"></td>
</tr>
</tbody></table>
</li>
<li><p>Jenkins立即构建</p>
<table>
<thead>
<tr>
<th align="center">点击任务test中的立即构建</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125200218093.png" srcset="/img/loading.gif" lazyload alt="image-20211125200218093"></td>
</tr>
</tbody></table>
</li>
<li><p>查看构建工程的日志，点击上述③的任务条即可</p>
<table>
<thead>
<tr>
<th align="center">查看任务拉取Git源码日志</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125201701443.png" srcset="/img/loading.gif" lazyload alt="image-20211125201701443"></td>
</tr>
</tbody></table>
<p>可以看到源码已经拉取带Jenkins本地，可以根据第三行日志信息，查看Jenkins本地拉取到的源码。</p>
</li>
<li><p>查看Jenkins容器中<a href="">&#x2F;var&#x2F;jenkins_home&#x2F;workspace&#x2F;test</a>的源码</p>
<table>
<thead>
<tr>
<th align="center">源码存放位置</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125201919108.png" srcset="/img/loading.gif" lazyload alt="image-20211125201919108"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="5-3-2-配置Maven构建代码"><a href="#5-3-2-配置Maven构建代码" class="headerlink" title="5.3.2 配置Maven构建代码"></a>5.3.2 配置Maven构建代码</h5><p>代码拉取到Jenkins本地后，需要在Jenkins中对代码进行构建，这里需要Maven的环境，而Maven需要Java的环境，接下来需要在Jenkins中安装JDK和Maven，并且配置到Jenkins服务。</p>
<ul>
<li><p>准备JDK、Maven压缩包通过数据卷映射到Jenkins容器内部</p>
<table>
<thead>
<tr>
<th align="center">数据卷存放位置</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125203757232.png" srcset="/img/loading.gif" lazyload alt="image-20211125203757232"></td>
</tr>
</tbody></table>
</li>
<li><p>解压压缩包，并配置Maven的settings.xml</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 阿里云镜像地址 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">mirror</span>&gt;</span>  <br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span>&gt;</span>alimaven<span class="hljs-tag">&lt;/<span class="hljs-name">id</span>&gt;</span>  <br>    <span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>aliyun maven<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>  <br>    <span class="hljs-tag">&lt;<span class="hljs-name">url</span>&gt;</span>http://maven.aliyun.com/nexus/content/groups/public/<span class="hljs-tag">&lt;/<span class="hljs-name">url</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">mirrorOf</span>&gt;</span>central<span class="hljs-tag">&lt;/<span class="hljs-name">mirrorOf</span>&gt;</span>          <br><span class="hljs-tag">&lt;/<span class="hljs-name">mirror</span>&gt;</span><br><span class="hljs-comment">&lt;!-- JDK1.8编译插件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">profile</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span>&gt;</span>jdk-1.8<span class="hljs-tag">&lt;/<span class="hljs-name">id</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">activation</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">activeByDefault</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">activeByDefault</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">jdk</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">jdk</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">activation</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">maven.compiler.source</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">maven.compiler.source</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">maven.compiler.target</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">maven.compiler.target</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">maven.compiler.compilerVersion</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">maven.compiler.compilerVersion</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>        <br><span class="hljs-tag">&lt;/<span class="hljs-name">profile</span>&gt;</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>Jenkins配置JDK&amp;Maven并保存</p>
<table>
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody><tr>
<td><img src="/../images/DevOps/Pictures/image-20211125204811759.png" srcset="/img/loading.gif" lazyload alt="image-20211125204811759"></td>
</tr>
<tr>
<td><img src="/../images/DevOps/Pictures/image-20211125204818869.png" srcset="/img/loading.gif" lazyload alt="image-20211125204818869"></td>
</tr>
</tbody></table>
</li>
<li><p>配置Jenkins任务构建代码</p>
<table>
<thead>
<tr>
<th align="center">配置Maven构建代码</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125205027013.png" srcset="/img/loading.gif" lazyload alt="image-20211125205027013"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125205020738.png" srcset="/img/loading.gif" lazyload alt="image-20211125205020738"></td>
</tr>
</tbody></table>
</li>
<li><p>立即构建测试，查看target下的jar包</p>
<table>
<thead>
<tr>
<th align="center">构建源码</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125205240208.png" srcset="/img/loading.gif" lazyload alt="image-20211125205240208"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125205725948.png" srcset="/img/loading.gif" lazyload alt="image-20211125205725948"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="5-3-3-配置Publish发布-amp-远程操作"><a href="#5-3-3-配置Publish发布-amp-远程操作" class="headerlink" title="5.3.3 配置Publish发布&amp;远程操作"></a>5.3.3 配置Publish发布&amp;远程操作</h5><p>jar包构建好之后，就可以根据情况发布到测试或生产环境，这里需要用到之前下载好的插件Publish Over SSH。</p>
<ul>
<li><p>配置Publish Over SSH连接测试、生产环境</p>
<table>
<thead>
<tr>
<th align="center">Publish Over SSH配置</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125210148202.png" srcset="/img/loading.gif" lazyload alt="image-20211125210148202"></td>
</tr>
</tbody></table>
</li>
<li><p>配置任务的构建后操作，发布jar包到目标服务</p>
<table>
<thead>
<tr>
<th align="center">配置构建后操作</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125205027013.png" srcset="/img/loading.gif" lazyload alt="image-20211125205027013"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125210424346.png" srcset="/img/loading.gif" lazyload alt="image-20211125210424346"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125210626631.png" srcset="/img/loading.gif" lazyload alt="image-20211125210626631"></td>
</tr>
</tbody></table>
</li>
<li><p>立即构建任务，并去目标服务查看</p>
<table>
<thead>
<tr>
<th align="center">立即构建</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125210755556.png" srcset="/img/loading.gif" lazyload alt="image-20211125210755556"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211125210826057.png" srcset="/img/loading.gif" lazyload alt="image-20211125210826057"></td>
</tr>
</tbody></table>
</li>
</ul>
<h3 id="六、CI、CD入门操作"><a href="#六、CI、CD入门操作" class="headerlink" title="六、CI、CD入门操作"></a>六、CI、CD入门操作</h3><p>基于Jenkins拉取GitLab的SpringBoot代码进行构建发布到测试环境实现持续集成</p>
<p>基于Jenkins拉取GitLab指定发行版本的SpringBoot代码进行构建发布到生产环境实现CD实现持续部署</p>
<h4 id="6-1-持续集成"><a href="#6-1-持续集成" class="headerlink" title="6.1 持续集成"></a>6.1 持续集成</h4><p>为了让程序代码可以自动推送到测试环境基于Docker服务运行，需要添加Docker配置和脚本文件让程序可以在集成到主干的同时运行起来。</p>
<ul>
<li><p>添加Dockerfile文件</p>
<table>
<thead>
<tr>
<th align="center">构建自定义镜像</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126161304485.png" srcset="/img/loading.gif" lazyload alt="image-20211126161304485"></td>
</tr>
</tbody></table>
</li>
<li><p>添加docker-compose.yml文件</p>
<table>
<thead>
<tr>
<th align="center">加载自定义镜像启动容器</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126161331991.png" srcset="/img/loading.gif" lazyload alt="image-20211126161331991"></td>
</tr>
</tbody></table>
</li>
<li><p>追加Jenkins构建后操作脚本命令</p>
<table>
<thead>
<tr>
<th align="center">构建后发布并执行脚本命令</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126161408514.png" srcset="/img/loading.gif" lazyload alt="image-20211126161408514"></td>
</tr>
</tbody></table>
</li>
<li><p>发布到GitLab后由Jenkins立即构建并托送到目标服务器</p>
<table>
<thead>
<tr>
<th align="center">构建日志</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126161448527.png" srcset="/img/loading.gif" lazyload alt="image-20211126161448527"></td>
</tr>
</tbody></table>
</li>
<li><p>测试部署到目标服务器程序</p>
<table>
<thead>
<tr>
<th align="center">查看目标服务器并测试接口</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126161504715.png" srcset="/img/loading.gif" lazyload alt="image-20211126161504715"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126161509411.png" srcset="/img/loading.gif" lazyload alt="image-20211126161509411"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="6-2-持续交付、部署"><a href="#6-2-持续交付、部署" class="headerlink" title="6.2 持续交付、部署"></a>6.2 持续交付、部署</h4><p>程序代码在经过多次集成操作到达最终可以交付，持续交付整体流程和持续集成类似，不过需要选取指定的发行版本</p>
<ul>
<li><p>下载Git Parameter插件</p>
<table>
<thead>
<tr>
<th align="center">下载Git Parameter</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126165209057.png" srcset="/img/loading.gif" lazyload alt="image-20211126165209057"></td>
</tr>
</tbody></table>
</li>
<li><p>设置项目参数化构建</p>
<table>
<thead>
<tr>
<th align="center">基于Git标签构建</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126165444124.png" srcset="/img/loading.gif" lazyload alt="image-20211126165444124"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126172828266.png" srcset="/img/loading.gif" lazyload alt="image-20211126172828266"></td>
</tr>
</tbody></table>
</li>
<li><p>给项目添加tag版本</p>
<table>
<thead>
<tr>
<th align="center">添加tag版本</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126165639286.png" srcset="/img/loading.gif" lazyload alt="image-20211126165639286"></td>
</tr>
</tbody></table>
</li>
<li><p>任务构建时，采用Shell方式构建，拉取指定tag版本代码</p>
<table>
<thead>
<tr>
<th align="center">切换指定标签并构建项目</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126174715028.png" srcset="/img/loading.gif" lazyload alt="image-20211126174715028"></td>
</tr>
</tbody></table>
</li>
<li><p>基于Parameter构建任务，任务发布到目标服务器</p>
<table>
<thead>
<tr>
<th align="center">构建任务</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211126174159487.png" srcset="/img/loading.gif" lazyload alt="image-20211126174159487"></td>
</tr>
</tbody></table>
</li>
</ul>
<h3 id="七、集成Sonar-Qube"><a href="#七、集成Sonar-Qube" class="headerlink" title="七、集成Sonar Qube"></a>七、集成Sonar Qube</h3><h4 id="7-1-Sonar-Qube介绍"><a href="#7-1-Sonar-Qube介绍" class="headerlink" title="7.1 Sonar Qube介绍"></a>7.1 Sonar Qube介绍</h4><p>Sonar Qube是一个开源的代码分析平台，支持Java、Python、PHP、JavaScript、CSS等25种以上的语言，可以检测出重复代码、代码漏洞、代码规范和安全性漏洞的问题。</p>
<p>Sonar Qube可以与多种软件整合进行代码扫描，比如Maven，Gradle，Git，Jenkins等，并且会将代码检测结果推送回Sonar Qube并且在系统提供的UI界面上显示出来</p>
<table>
<thead>
<tr>
<th align="center">Sonar Qube的UI界面</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129190039986.png" srcset="/img/loading.gif" lazyload alt="image-20211129190039986"></td>
</tr>
</tbody></table>
<h4 id="7-2-Sonar-Qube环境搭建"><a href="#7-2-Sonar-Qube环境搭建" class="headerlink" title="7.2 Sonar Qube环境搭建"></a>7.2 Sonar Qube环境搭建</h4><h5 id="7-2-1-Sonar-Qube安装"><a href="#7-2-1-Sonar-Qube安装" class="headerlink" title="7.2.1 Sonar Qube安装"></a>7.2.1 Sonar Qube安装</h5><p>Sonar Qube在7.9版本中已经放弃了对MySQL的支持，并且建议在商业环境中采用PostgreSQL，那么安装Sonar Qube时需要依赖PostgreSQL。</p>
<p>并且这里会安装Sonar Qube的长期支持版本<a href="">8.9</a></p>
<ul>
<li><p>拉取镜像</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker pull postgres<br>docker pull sonarqube:8.9.3-community<br></code></pre></td></tr></table></figure>
</li>
<li><p>编写docker-compoe.yml</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">version:</span> <span class="hljs-string">&quot;3.1&quot;</span><br><span class="hljs-attr">services:</span><br>  <span class="hljs-attr">db:</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">postgres</span><br>    <span class="hljs-attr">container_name:</span> <span class="hljs-string">db</span><br>    <span class="hljs-attr">ports:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-number">5432</span><span class="hljs-string">:5432</span><br>    <span class="hljs-attr">networks:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">sonarnet</span><br>    <span class="hljs-attr">environment:</span><br>      <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">sonar</span><br>      <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">sonar</span><br>  <span class="hljs-attr">sonarqube:</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">sonarqube:8.9.3-community</span><br>    <span class="hljs-attr">container_name:</span> <span class="hljs-string">sonarqube</span><br>    <span class="hljs-attr">depends_on:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">db</span><br>    <span class="hljs-attr">ports:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&quot;9000:9000&quot;</span><br>    <span class="hljs-attr">networks:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">sonarnet</span><br>    <span class="hljs-attr">environment:</span><br>      <span class="hljs-attr">SONAR_JDBC_URL:</span> <span class="hljs-string">jdbc:postgresql://db:5432/sonar</span><br>      <span class="hljs-attr">SONAR_JDBC_USERNAME:</span> <span class="hljs-string">sonar</span><br>      <span class="hljs-attr">SONAR_JDBC_PASSWORD:</span> <span class="hljs-string">sonar</span><br><span class="hljs-attr">networks:</span><br>  <span class="hljs-attr">sonarnet:</span><br>    <span class="hljs-attr">driver:</span> <span class="hljs-string">bridge</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>启动容器</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">docker-compose up -d</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>需要设置sysctl.conf文件信息</p>
<table>
<thead>
<tr>
<th align="center">设置vm.max_map_count</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211207145215817.png" srcset="/img/loading.gif" lazyload alt="image-20211207145215817"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211207145342350.png" srcset="/img/loading.gif" lazyload alt="image-20211207145342350"></td>
</tr>
</tbody></table>
<p>并执行命令刷新</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs css">sysctl -<span class="hljs-selector-tag">p</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>重新启动需要一定时间启动，可以可以查看容器日志，看到如下内容代表启动成功</p>
<table>
<thead>
<tr>
<th align="center">容器日志</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129191426344.png" srcset="/img/loading.gif" lazyload alt="image-20211129191426344"></td>
</tr>
</tbody></table>
</li>
<li><p>访问Sonar Qube首页</p>
<table>
<thead>
<tr>
<th align="center">登录</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129191537050.png" srcset="/img/loading.gif" lazyload alt="image-20211129191537050"></td>
</tr>
</tbody></table>
</li>
<li><p>还需要重新设置一次密码</p>
<table>
<thead>
<tr>
<th align="center">重新设置密码</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129193824428.png" srcset="/img/loading.gif" lazyload alt="image-20211129193824428"></td>
</tr>
</tbody></table>
</li>
<li><p>Sonar Qube首页</p>
<table>
<thead>
<tr>
<th align="center">Sonar Qube首页</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129194148239.png" srcset="/img/loading.gif" lazyload alt="image-20211129194148239"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="7-2-2-安装中文插件"><a href="#7-2-2-安装中文插件" class="headerlink" title="7.2.2 安装中文插件"></a>7.2.2 安装中文插件</h5><table>
<thead>
<tr>
<th align="center">安装中文插件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129194621820.png" srcset="/img/loading.gif" lazyload alt="image-20211129194621820"></td>
</tr>
</tbody></table>
<p>安装成功后需要重启，安装失败重新点击install重装即可。</p>
<p>安装成功后，会查看到重启按钮，点击即可</p>
<table>
<thead>
<tr>
<th align="center">重启按钮</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129194748765.png" srcset="/img/loading.gif" lazyload alt="image-20211129194748765"></td>
</tr>
</tbody></table>
<p>重启后查看效果</p>
<table>
<thead>
<tr>
<th align="center">首页效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129194931944.png" srcset="/img/loading.gif" lazyload alt="image-20211129194931944"></td>
</tr>
</tbody></table>
<h4 id="7-3-Sonar-Qube基本使用"><a href="#7-3-Sonar-Qube基本使用" class="headerlink" title="7.3 Sonar Qube基本使用"></a>7.3 Sonar Qube基本使用</h4><p>Sonar Qube的使用方式很多，Maven可以整合，也可以采用sonar-scanner的方式，再查看Sonar Qube的检测效果</p>
<h5 id="7-3-1-Maven实现代码检测"><a href="#7-3-1-Maven实现代码检测" class="headerlink" title="7.3.1 Maven实现代码检测"></a>7.3.1 Maven实现代码检测</h5><ul>
<li><p>修改Maven的settings.xml文件配置Sonar Qube信息</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">profile</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span>&gt;</span>sonar<span class="hljs-tag">&lt;/<span class="hljs-name">id</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">activation</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">activeByDefault</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">activeByDefault</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">activation</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">sonar.login</span>&gt;</span>admin<span class="hljs-tag">&lt;/<span class="hljs-name">sonar.login</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">sonar.password</span>&gt;</span>123456789<span class="hljs-tag">&lt;/<span class="hljs-name">sonar.password</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">sonar.host.url</span>&gt;</span>http://192.168.11.11:9000<span class="hljs-tag">&lt;/<span class="hljs-name">sonar.host.url</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">profile</span>&gt;</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>在代码位置执行命令：mvn sonar:sonar</p>
<table>
<thead>
<tr>
<th align="center">执行代码检测</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129195430146.png" srcset="/img/loading.gif" lazyload alt="image-20211129195430146"></td>
</tr>
</tbody></table>
</li>
<li><p>查看Sonar Qube界面检测结果</p>
<table>
<thead>
<tr>
<th align="center">Sonar Qube检测结果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129195503762.png" srcset="/img/loading.gif" lazyload alt="image-20211129195503762"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="7-3-2-Sonar-scanner实现代码检测"><a href="#7-3-2-Sonar-scanner实现代码检测" class="headerlink" title="7.3.2 Sonar-scanner实现代码检测"></a>7.3.2 Sonar-scanner实现代码检测</h5><ul>
<li><p>下载Sonar-scanner：<a target="_blank" rel="noopener" href="https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/">https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/</a></p>
<p>下载4.6.x版本即可，要求Linux版本</p>
</li>
<li><p>解压并配置sonar服务端信息</p>
<ul>
<li><p>由于是zip压缩包，需要安装unzip解压插件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">yum -y install unzip<br></code></pre></td></tr></table></figure>
</li>
<li><p>解压压缩包</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">unzip sonar-scanner-cli/sonar-scanner-cli-4.6.0.2311-linux.zip<br></code></pre></td></tr></table></figure>
</li>
<li><p>配置sonarQube服务端地址，修改conf下的sonar-scanner.properties</p>
<table>
<thead>
<tr>
<th align="center">配置服务端信息</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130140043382.png" srcset="/img/loading.gif" lazyload alt="image-20211130140043382"></td>
</tr>
</tbody></table>
</li>
</ul>
</li>
<li><p>执行命令检测代码</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 在项目所在目录执行以下命令</span><br>~/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=demo -Dsonar.projectKey=java -Dsonar.java.binaries=target/<br></code></pre></td></tr></table></figure>

<p><a href="">Ps：主要查看我的sonar-scanner执行命令的位置</a></p>
<table>
<thead>
<tr>
<th align="center">查看日志信息</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130141303457.png" srcset="/img/loading.gif" lazyload alt="image-20211130141303457"></td>
</tr>
</tbody></table>
</li>
<li><p>查看SonarQube界面检测结果</p>
<table>
<thead>
<tr>
<th align="center">检测结果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130144608025.png" srcset="/img/loading.gif" lazyload alt="image-20211130144608025"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="7-4-Jenkins集成Sonar-Qube"><a href="#7-4-Jenkins集成Sonar-Qube" class="headerlink" title="7.4 Jenkins集成Sonar Qube"></a>7.4 Jenkins集成Sonar Qube</h4><p>Jenkins继承Sonar Qube实现代码扫描需要先下载整合插件</p>
<h5 id="7-4-1-Jenkins安装插件"><a href="#7-4-1-Jenkins安装插件" class="headerlink" title="7.4.1 Jenkins安装插件"></a>7.4.1 Jenkins安装插件</h5><table>
<thead>
<tr>
<th align="center">下载Sonar Qube插件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129201625561.png" srcset="/img/loading.gif" lazyload alt="image-20211129201625561"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129201607240.png" srcset="/img/loading.gif" lazyload alt="image-20211129201607240"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129202147390.png" srcset="/img/loading.gif" lazyload alt="image-20211129202147390"></td>
</tr>
</tbody></table>
<h5 id="7-4-2-Jenkins配置Sonar-Qube"><a href="#7-4-2-Jenkins配置Sonar-Qube" class="headerlink" title="7.4.2 Jenkins配置Sonar Qube"></a>7.4.2 Jenkins配置Sonar Qube</h5><ul>
<li><p>开启Sonar Qube权限验证</p>
<table>
<thead>
<tr>
<th align="center">开启Sonar Qube权限校验</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130144850186.png" srcset="/img/loading.gif" lazyload alt="image-20211130144850186"></td>
</tr>
</tbody></table>
</li>
<li><p>获取Sonar Qube的令牌</p>
<table>
<thead>
<tr>
<th align="center">获取令牌</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211129203102334.png" srcset="/img/loading.gif" lazyload alt="image-20211129203102334"></td>
</tr>
</tbody></table>
</li>
<li><p>配置Jenkins的Sonar Qube信息</p>
<table>
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody><tr>
<td><img src="/../images/DevOps/Pictures/image-20211129203235019.png" srcset="/img/loading.gif" lazyload alt="image-20211129203235019"></td>
</tr>
<tr>
<td><img src="/../images/DevOps/Pictures/image-20211129203342171.png" srcset="/img/loading.gif" lazyload alt="image-20211129203342171"></td>
</tr>
<tr>
<td><img src="/../images/DevOps/Pictures/image-20211129203457604.png" srcset="/img/loading.gif" lazyload alt="image-20211129203457604"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="7-4-3-配置Sonar-scanner"><a href="#7-4-3-配置Sonar-scanner" class="headerlink" title="7.4.3 配置Sonar-scanner"></a>7.4.3 配置Sonar-scanner</h5><ul>
<li><p>将Sonar-scaner添加到Jenkins数据卷中并配置全局配置</p>
<table>
<thead>
<tr>
<th align="center">配置Sonar-scanner</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130153628925.png" srcset="/img/loading.gif" lazyload alt="image-20211130153628925"></td>
</tr>
</tbody></table>
</li>
<li><p>配置任务的Sonar-scanner</p>
<table>
<thead>
<tr>
<th align="center">配置任务的Sonar-scanner</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130155849143.png" srcset="/img/loading.gif" lazyload alt="image-20211130155849143"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="7-4-4-构建任务"><a href="#7-4-4-构建任务" class="headerlink" title="7.4.4 构建任务"></a>7.4.4 构建任务</h5><table>
<thead>
<tr>
<th align="center">构建任务</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130160017465.png" srcset="/img/loading.gif" lazyload alt="image-20211130160017465"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130160047648.png" srcset="/img/loading.gif" lazyload alt="image-20211130160047648"></td>
</tr>
</tbody></table>
<h3 id="八、集成Harbor"><a href="#八、集成Harbor" class="headerlink" title="八、集成Harbor"></a>八、集成Harbor</h3><h4 id="8-1-Harbor介绍"><a href="#8-1-Harbor介绍" class="headerlink" title="8.1 Harbor介绍"></a>8.1 Harbor介绍</h4><p>前面在部署项目时，我们主要采用Jenkins推送jar包到指定服务器，再通过脚本命令让目标服务器对当前jar进行部署，这种方式在项目较多时，每个目标服务器都需要将jar包制作成自定义镜像再通过docker进行启动，重复操作比较多，会降低项目部署时间。</p>
<p>我们可以通过Harbor作为私有的Docker镜像仓库。让Jenkins统一将项目打包并制作成Docker镜像发布到Harbor仓库中，只需要通知目标服务，让目标服务统一去Harbor仓库上拉取镜像并在本地部署即可。</p>
<p>Docker官方提供了Registry镜像仓库，但是Registry的功能相对简陋。Harbor是VMware公司提供的一款镜像仓库，提供了权限控制、分布式发布、强大的安全扫描与审查机制等功能</p>
<h4 id="8-2-Harbor安装"><a href="#8-2-Harbor安装" class="headerlink" title="8.2 Harbor安装"></a>8.2 Harbor安装</h4><p>这里采用原生的方式安装Harbor。</p>
<ul>
<li><p>下载Harbor安装包：<a target="_blank" rel="noopener" href="https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz">https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz</a></p>
</li>
<li><p>拖拽到Linux并解压：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">tar</span> -zxvf harbor-offline-installer-v2.<span class="hljs-number">3</span>.<span class="hljs-number">4</span>.tgz -C /usr/local/<br></code></pre></td></tr></table></figure>
</li>
<li><p>修改Harbor配置文件：</p>
<ul>
<li><p>首先复制一份harbor.yml配置</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-built_in">cp</span> harbor.yml.tmpl harbor.yml<br></code></pre></td></tr></table></figure>
</li>
<li><p>编辑harbor.yml配置文件</p>
<table>
<thead>
<tr>
<th align="center">配置Harbor文件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130215555218.png" srcset="/img/loading.gif" lazyload alt="image-20211130215555218"></td>
</tr>
</tbody></table>
</li>
</ul>
</li>
<li><p>启动Harbor</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">./install.sh<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">查看日志</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130215941857.png" srcset="/img/loading.gif" lazyload alt="image-20211130215941857"></td>
</tr>
</tbody></table>
</li>
<li><p>登录Harbor</p>
<table>
<thead>
<tr>
<th align="center">登录Harbor</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130220028840.png" srcset="/img/loading.gif" lazyload alt="image-20211130220028840"></td>
</tr>
</tbody></table>
</li>
<li><p>首页信息</p>
<table>
<thead>
<tr>
<th align="center">首页信息</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211130220111602.png" srcset="/img/loading.gif" lazyload alt="image-20211130220111602"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="8-3-Harbor使用方式"><a href="#8-3-Harbor使用方式" class="headerlink" title="8.3 Harbor使用方式"></a>8.3 Harbor使用方式</h4><p>Harbor作为镜像仓库，主要的交互方式就是将镜像上传到Harbor上，以及从Harbor上下载指定镜像</p>
<p>在传输镜像前，可以先使用Harbor提供的权限管理，将项目设置为私有项目，并对不同用户设置不同角色，从而更方便管理镜像。</p>
<h5 id="8-3-1-添加用户构建项目"><a href="#8-3-1-添加用户构建项目" class="headerlink" title="8.3.1 添加用户构建项目"></a>8.3.1 添加用户构建项目</h5><ul>
<li><p>创建用户</p>
<table>
<thead>
<tr>
<th align="center">创建用户</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201213427157.png" srcset="/img/loading.gif" lazyload alt="image-20211201213427157"></td>
</tr>
</tbody></table>
</li>
<li><p>构建项目（设置为私有）</p>
<table>
<thead>
<tr>
<th align="center">构建项目</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201213751780.png" srcset="/img/loading.gif" lazyload alt="image-20211201213751780"></td>
</tr>
</tbody></table>
</li>
<li><p>给项目追加用户</p>
<table>
<thead>
<tr>
<th align="center">追加用户管理</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201213832458.png" srcset="/img/loading.gif" lazyload alt="image-20211201213832458"></td>
</tr>
</tbody></table>
</li>
<li><p>切换测试用户</p>
<table>
<thead>
<tr>
<th align="center">切换测试用户</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201214008303.png" srcset="/img/loading.gif" lazyload alt="image-20211201214008303"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="8-3-2-发布镜像到Harbor"><a href="#8-3-2-发布镜像到Harbor" class="headerlink" title="8.3.2 发布镜像到Harbor"></a>8.3.2 发布镜像到Harbor</h5><ul>
<li><p>修改镜像名称</p>
<p>名称要求：<a href="">harbor地址&#x2F;项目名&#x2F;镜像名:版本</a></p>
<table>
<thead>
<tr>
<th>修改镜像名称</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/../images/DevOps/Pictures/image-20211201221040200.png" srcset="/img/loading.gif" lazyload alt="image-20211201221040200"></td>
</tr>
</tbody></table>
</li>
<li><p>修改daemon.json，支持Docker仓库，并重启Docker</p>
<table>
<thead>
<tr>
<th align="center">修改daemon.json，支持Docker仓库</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201215931237.png" srcset="/img/loading.gif" lazyload alt="image-20211201215931237"></td>
</tr>
</tbody></table>
</li>
<li><p>设置登录仓库信息</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker login -u 用户名 -p 密码 Harbor地址<br></code></pre></td></tr></table></figure>
</li>
<li><p>推送镜像到Harbor</p>
<table>
<thead>
<tr>
<th align="center">推送镜像到Harbor</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201221225196.png" srcset="/img/loading.gif" lazyload alt="image-20211201221225196"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201221300055.png" srcset="/img/loading.gif" lazyload alt="image-20211201221300055"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="8-3-3-从Harbor拉取镜像ls"><a href="#8-3-3-从Harbor拉取镜像ls" class="headerlink" title="8.3.3 从Harbor拉取镜像ls"></a>8.3.3 从Harbor拉取镜像ls</h5><p>跟传统方式一样，不过需要先配置<a href="">&#x2F;etc&#x2F;docker&#x2F;daemon.json</a>文件</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;registry-mirrors&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">&quot;https://pee6w651.mirror.aliyuncs.com&quot;</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;insecure-registries&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">&quot;192.168.11.11:80&quot;</span><span class="hljs-punctuation">]</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">拉取镜像</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211201222450091.png" srcset="/img/loading.gif" lazyload alt="image-20211201222450091"></td>
</tr>
</tbody></table>
<h5 id="8-3-4-Jenkins容器使用宿主机Docker"><a href="#8-3-4-Jenkins容器使用宿主机Docker" class="headerlink" title="8.3.4 Jenkins容器使用宿主机Docker"></a>8.3.4 Jenkins容器使用宿主机Docker</h5><p>构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可。</p>
<p>设置Jenkins容器使用宿主机Docker</p>
<ul>
<li><p>设置宿主机docker.sock权限：</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh">sudo <span class="hljs-built_in">chown</span> root:root /var/run/docker.sock<br>sudo <span class="hljs-built_in">chmod</span> o+rw /var/run/docker.sock<br></code></pre></td></tr></table></figure>
</li>
<li><p>添加数据卷</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">version:</span> <span class="hljs-string">&quot;3.1&quot;</span><br><span class="hljs-attr">services:</span><br>  <span class="hljs-attr">jenkins:</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">jenkins/jenkins</span><br>    <span class="hljs-attr">container_name:</span> <span class="hljs-string">jenkins</span><br>    <span class="hljs-attr">ports:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-number">8080</span><span class="hljs-string">:8080</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-number">50000</span><span class="hljs-string">:50000</span><br>    <span class="hljs-attr">volumes:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">./data/:/var/jenkins_home/</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">/usr/bin/docker:/usr/bin/docker</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">/var/run/docker.sock:/var/run/docker.sock</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">/etc/docker/daemon.json:/etc/docker/daemon.json</span><br></code></pre></td></tr></table></figure></li>
</ul>
<h5 id="8-3-5-添加构建操作"><a href="#8-3-5-添加构建操作" class="headerlink" title="8.3.5 添加构建操作"></a>8.3.5 添加构建操作</h5><table>
<thead>
<tr>
<th align="center">制作自定义镜像</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211229155834500.png" srcset="/img/loading.gif" lazyload alt="image-20211229155834500"></td>
</tr>
</tbody></table>
<h5 id="8-3-6-编写部署脚本"><a href="#8-3-6-编写部署脚本" class="headerlink" title="8.3.6 编写部署脚本"></a>8.3.6 编写部署脚本</h5><p>部署项目需要通过Publish Over SSH插件，让目标服务器执行命令。为了方便一次性实现拉取镜像和启动的命令，推荐采用脚本文件的方式。</p>
<p>添加脚本文件到目标服务器，再通过Publish Over SSH插件让目标服务器执行脚本即可。</p>
<ul>
<li><p>编写脚本文件，添加到目标服务器</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs sh">harbor_addr=<span class="hljs-variable">$1</span><br>harbor_repo=<span class="hljs-variable">$2</span><br>project=<span class="hljs-variable">$3</span><br>version=<span class="hljs-variable">$4</span><br>container_port=<span class="hljs-variable">$5</span><br>host_port=<span class="hljs-variable">$6</span><br><br></code></pre></td></tr></table></figure></li>
</ul>
<p>imageName&#x3D;$harbor_addr&#x2F;$harbor_repo&#x2F;$project:$version</p>
<p>  containerId&#x3D;<code>docker ps -a | grep $&#123;project&#125; | awk &#39;&#123;print $1&#125;&#39;</code></p>
<p>  echo $containerId</p>
<p>  if [ “$containerId” !&#x3D; “” ] ; then<br>    docker stop $containerId<br>      docker rm $containerId<br>    echo “Delete Container Success”<br>  fi</p>
<p>  tag&#x3D;<code>docker images | grep $&#123;project&#125; | awk &#39;&#123;print $2&#125;&#39;</code></p>
<p>echo $tag</p>
<p>if [ “$tag” &#x3D;~ “$version” ] ; then<br>      docker rmi -f $imageName<br>    echo “Delete Image Success”<br>  fi</p>
<p>  docker login -u admin -p Harbor12345 $harbor_addr<br>  docker pull $imageName</p>
<p>docker run -d -p $host_port:$container_port –name $project $imageName</p>
<p>echo “Start Container Success”</p>
  <figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs"><br>并设置权限为可执行<br><br></code></pre></td></tr></table></figure>

<p>  chmod a+x deploy.sh</p>
  <figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><code class="hljs elixir">  <br>  |                    如图                    |<br>  | <span class="hljs-symbol">:--------------------------------------</span>: |<br>  | ![image<span class="hljs-number">-20211203192047357</span>](<span class="hljs-title class_">Pictures</span>/image<span class="hljs-number">-20211203192047357</span>.png) |<br><br><span class="hljs-comment">##### 8.3.7 配置构建后操作</span><br><br>|                  执行脚本文件                  |<br>| <span class="hljs-symbol">:--------------------------------------</span>: |<br>| ![image<span class="hljs-number">-20211229155949038</span>](<span class="hljs-title class_">Pictures</span>/image<span class="hljs-number">-20211229155949038</span>.png) |<br><br><br><br><span class="hljs-comment">### 九、Jenkins流水线</span><br><br><span class="hljs-comment">#### 9.1 Jenkins流水线任务介绍</span><br><br>之前采用<span class="hljs-title class_">Jenkins</span>的自由风格构建的项目，每个步骤流程都要通过不同的方式设置，并且构建过程中整体流程是不可见的，无法确认每个流程花费的时间，并且问题不方便定位问题。<br><br><span class="hljs-title class_">Jenkins</span>的<span class="hljs-title class_">Pipeline</span>可以让项目的发布整体流程可视化，明确执行的阶段，可以快速的定位问题。并且整个项目的生命周期可以通过一个<span class="hljs-title class_">Jenkinsfile</span>文件管理，而且<span class="hljs-title class_">Jenkinsfile</span>文件是可以放在项目中维护。<br><br>所以<span class="hljs-title class_">Pipeline</span>相对自由风格或者其他的项目风格更容易操作。<br><br><span class="hljs-comment">#### 9.2 Jenkins流水线任务</span><br><br><span class="hljs-comment">##### 9.2.1 构建Jenkins流水线任务</span><br><br>- 构建任务<br><br>  | 构建<span class="hljs-title class_">Jenkins</span>流水线任务                           |<br>  | ---------------------------------------- |<br>  | ![image<span class="hljs-number">-20211202144429302</span>](<span class="hljs-title class_">Pictures</span>/image<span class="hljs-number">-20211202144429302</span>.png) |<br><br>- 生成<span class="hljs-title class_">Groovy</span>脚本<br><br>  |             <span class="hljs-title class_">Hello</span> <span class="hljs-title class_">World</span>脚本生成              |<br>  | <span class="hljs-symbol">:--------------------------------------</span>: |<br>  | ![image<span class="hljs-number">-20211202144531749</span>](<span class="hljs-title class_">Pictures</span>/image<span class="hljs-number">-20211202144531749</span>.png) |<br><br>- 构建后查看视图<br><br>  |                 构建后查看视图                  |<br>  | <span class="hljs-symbol">:--------------------------------------</span>: |<br>  | ![image<span class="hljs-number">-20211202144616117</span>](<span class="hljs-title class_">Pictures</span>/image<span class="hljs-number">-20211202144616117</span>.png) |<br><br><span class="hljs-comment">##### 9.2.2 Groovy脚本</span><br><br>- <span class="hljs-title class_">Groovy</span>脚本基础语法<br><br>  ```sh<br>  // 所有脚本命令包含在pipeline&#123;&#125;中<br>  pipeline &#123;  <br>  	// 指定任务在哪个节点执行（<span class="hljs-title class_">Jenkins</span>支持分布式）<br>      agent any<br>      <br>      // 配置全局环境，指定变量名=变量值信息<br>      environment&#123;<br>      	host = <span class="hljs-string">&#x27;192.168.11.11&#x27;</span><br>      &#125;<br><br>      // 存放所有任务的合集<br>      stages &#123;<br>      	// 单个任务<br>          stage(<span class="hljs-string">&#x27;任务1&#x27;</span>) &#123;<br>          	// 实现任务的具体流程<br>              steps &#123;<br>                  echo <span class="hljs-string">&#x27;do something&#x27;</span><br>              &#125;<br>          &#125;<br>  		// 单个任务<br>          stage(<span class="hljs-string">&#x27;任务2&#x27;</span>) &#123;<br>          	// 实现任务的具体流程<br>              steps &#123;<br>                  echo <span class="hljs-string">&#x27;do something&#x27;</span><br>              &#125;<br>          &#125;<br>          // ……<br>      &#125;<br>  &#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>编写例子测试</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br><br>    // 存放所有任务的合集<br>    stages &#123;<br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>) &#123;<br>            steps &#123;<br>                <span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;拉取Git代码&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;检测代码质量&#x27;</span>) &#123;<br>            steps &#123;<br>                <span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;检测代码质量&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;构建代码&#x27;</span>) &#123;<br>            steps &#123;<br>                <span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;构建代码&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;制作自定义镜像并发布Harbor&#x27;</span>) &#123;<br>            steps &#123;<br>                <span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;制作自定义镜像并发布Harbor&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;基于Harbor部署工程&#x27;</span>) &#123;<br>            steps &#123;<br>                <span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;基于Harbor部署工程&#x27;</span><br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">配置Grovvy脚本</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202145155428.png" srcset="/img/loading.gif" lazyload alt="image-20211202145155428"></td>
</tr>
</tbody></table>
</li>
<li><p>查看效果</p>
<table>
<thead>
<tr>
<th align="center">查看效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202145240166.png" srcset="/img/loading.gif" lazyload alt="image-20211202145240166"></td>
</tr>
</tbody></table>
</li>
</ul>
<p><a href="">Ps：涉及到特定脚本，Jenkins给予了充足的提示，可以自动生成命令</a></p>
<table>
<thead>
<tr>
<th align="center">生成命令位置</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202145349043.png" srcset="/img/loading.gif" lazyload alt="image-20211202145349043"></td>
</tr>
</tbody></table>
<h5 id="9-2-3-Jenkinsfile实现"><a href="#9-2-3-Jenkinsfile实现" class="headerlink" title="9.2.3 Jenkinsfile实现"></a>9.2.3 Jenkinsfile实现</h5><p>Jenkinsfile方式需要将脚本内容编写到项目中的Jenkinsfile文件中，每次构建会自动拉取项目并且获取项目中Jenkinsfile文件对项目进行构建</p>
<ul>
<li><p>配置pipeline</p>
<table>
<thead>
<tr>
<th align="center">配置pipeline</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202151127254.png" srcset="/img/loading.gif" lazyload alt="image-20211202151127254"></td>
</tr>
</tbody></table>
</li>
<li><p>准备Jenkinsfile</p>
<table>
<thead>
<tr>
<th align="center">准备Jenkinsfile文件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202151155145.png" srcset="/img/loading.gif" lazyload alt="image-20211202151155145"></td>
</tr>
</tbody></table>
</li>
<li><p>测试效果</p>
<table>
<thead>
<tr>
<th align="center">测试效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202151225161.png" srcset="/img/loading.gif" lazyload alt="image-20211202151225161"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="9-3-Jenkins流水线任务实现"><a href="#9-3-Jenkins流水线任务实现" class="headerlink" title="9.3 Jenkins流水线任务实现"></a>9.3 Jenkins流水线任务实现</h4><h5 id="9-3-1-参数化构建"><a href="#9-3-1-参数化构建" class="headerlink" title="9.3.1 参数化构建"></a>9.3.1 参数化构建</h5><p>添加参数化构建，方便选择不的项目版本</p>
<table>
<thead>
<tr>
<th align="center">Git参数化构建</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202191944277.png" srcset="/img/loading.gif" lazyload alt="image-20211202191944277"></td>
</tr>
</tbody></table>
<h5 id="9-3-2-拉取Git代码"><a href="#9-3-2-拉取Git代码" class="headerlink" title="9.3.2 拉取Git代码"></a>9.3.2 拉取Git代码</h5><p>通过流水线语法生成Checkout代码的脚本</p>
<table>
<thead>
<tr>
<th align="center">语法生成</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211202192047619.png" srcset="/img/loading.gif" lazyload alt="image-20211202192047619"></td>
</tr>
</tbody></table>
<p><img src="C:\Users\Administrator\Desktop\DevOps笔记-MarkDown原版\DevOps\Pictures\image-20211202192129895.png" srcset="/img/loading.gif" lazyload alt="image-20211202192129895">将*&#x2F;master更改为标签<a href="">${tag}</a></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br>    stages &#123;<br><br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>) &#123;<br>            steps &#123;<br>                checkout([<span class="hljs-variable">$class</span>: <span class="hljs-string">&#x27;GitSCM&#x27;</span>, branches: [[name: <span class="hljs-string">&#x27;$&#123;tag&#125;&#x27;</span>]], extensions: [], userRemoteConfigs: [[url: <span class="hljs-string">&#x27;http://49.233.115.171:8929/root/test.git&#x27;</span>]]])<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h5 id="9-3-3-构建代码"><a href="#9-3-3-构建代码" class="headerlink" title="9.3.3 构建代码"></a>9.3.3 构建代码</h5><p>通过脚本执行mvn的构建命令</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br><br>    stages &#123;<br><br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>) &#123;<br>            steps &#123;<br>                checkout([<span class="hljs-variable">$class</span>: <span class="hljs-string">&#x27;GitSCM&#x27;</span>, branches: [[name: <span class="hljs-string">&#x27;$&#123;tag&#125;&#x27;</span>]], extensions: [], userRemoteConfigs: [[url: <span class="hljs-string">&#x27;http://49.233.115.171:8929/root/test.git&#x27;</span>]]])<br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;构建代码&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/maven/bin/mvn clean package -DskipTests&#x27;</span><br>            &#125;<br>        &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>



<h5 id="9-3-4-代码质量检测"><a href="#9-3-4-代码质量检测" class="headerlink" title="9.3.4 代码质量检测"></a>9.3.4 代码质量检测</h5><p>通过脚本执行sonar-scanner命令即可</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br><br>    stages &#123;<br><br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>) &#123;<br>            steps &#123;<br>                checkout([<span class="hljs-variable">$class</span>: <span class="hljs-string">&#x27;GitSCM&#x27;</span>, branches: [[name: <span class="hljs-string">&#x27;$&#123;tag&#125;&#x27;</span>]], extensions: [], userRemoteConfigs: [[url: <span class="hljs-string">&#x27;http://49.233.115.171:8929/root/test.git&#x27;</span>]]])<br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;构建代码&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/maven/bin/mvn clean package -DskipTests&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;检测代码质量&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=$&#123;JOB_NAME&#125; -Dsonar.projectKey=$&#123;JOB_NAME&#125; -Dsonar.java.binaries=target/ -Dsonar.login=31388be45653876c1f51ec02f0d478e2d9d0e1fa&#x27;</span> <br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>



<h5 id="9-3-5-制作自定义镜像并发布"><a href="#9-3-5-制作自定义镜像并发布" class="headerlink" title="9.3.5 制作自定义镜像并发布"></a>9.3.5 制作自定义镜像并发布</h5><ul>
<li><p>生成自定义镜像脚本</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br>    environment&#123;<br>        harborHost = <span class="hljs-string">&#x27;192.168.11.11:80&#x27;</span><br>        harborRepo = <span class="hljs-string">&#x27;repository&#x27;</span><br>        harborUser = <span class="hljs-string">&#x27;DevOps&#x27;</span><br>        harborPasswd = <span class="hljs-string">&#x27;P@ssw0rd&#x27;</span><br>    &#125;<br><br>    // 存放所有任务的合集<br>    stages &#123;<br><br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>) &#123;<br>            steps &#123;<br>                checkout([<span class="hljs-variable">$class</span>: <span class="hljs-string">&#x27;GitSCM&#x27;</span>, branches: [[name: <span class="hljs-string">&#x27;$&#123;tag&#125;&#x27;</span>]], extensions: [], userRemoteConfigs: [[url: <span class="hljs-string">&#x27;http://49.233.115.171:8929/root/test.git&#x27;</span>]]])<br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;构建代码&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/maven/bin/mvn clean package -DskipTests&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;检测代码质量&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=$&#123;JOB_NAME&#125; -Dsonar.projectKey=$&#123;JOB_NAME&#125; -Dsonar.java.binaries=target/ -Dsonar.login=31388be45653876c1f51ec02f0d478e2d9d0e1fa&#x27;</span> <br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;制作自定义镜像并发布Harbor&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">&#x27;cp ./target/*.jar ./docker/</span><br><span class="hljs-string">                cd ./docker</span><br><span class="hljs-string">                docker build -t $&#123;JOB_NAME&#125;:$&#123;tag&#125; ./&#x27;</span><span class="hljs-string">&#x27;&#x27;</span><br><br>                sh <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">&#x27;docker login -u $&#123;harborUser&#125; -p $&#123;harborPasswd&#125; $&#123;harborHost&#125;</span><br><span class="hljs-string">                docker tag $&#123;JOB_NAME&#125;:$&#123;tag&#125; $&#123;harborHost&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:$&#123;tag&#125;</span><br><span class="hljs-string">                docker push $&#123;harborHost&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:$&#123;tag&#125;&#x27;</span><span class="hljs-string">&#x27;&#x27;</span><br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
</li>
<li><p>生成Publish Over SSH脚本</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br>    environment&#123;<br>        harborHost = <span class="hljs-string">&#x27;192.168.11.11:80&#x27;</span><br>        harborRepo = <span class="hljs-string">&#x27;repository&#x27;</span><br>        harborUser = <span class="hljs-string">&#x27;DevOps&#x27;</span><br>        harborPasswd = <span class="hljs-string">&#x27;P@ssw0rd&#x27;</span><br>    &#125;<br><br>    // 存放所有任务的合集<br>    stages &#123;<br><br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>) &#123;<br>            steps &#123;<br>                checkout([<span class="hljs-variable">$class</span>: <span class="hljs-string">&#x27;GitSCM&#x27;</span>, branches: [[name: <span class="hljs-string">&#x27;$&#123;tag&#125;&#x27;</span>]], extensions: [], userRemoteConfigs: [[url: <span class="hljs-string">&#x27;http://49.233.115.171:8929/root/test.git&#x27;</span>]]])<br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;构建代码&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/maven/bin/mvn clean package -DskipTests&#x27;</span><br>            &#125;<br>        &#125;docker<br><br>        stage(<span class="hljs-string">&#x27;检测代码质量&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=$&#123;JOB_NAME&#125; -Dsonar.projectKey=$&#123;JOB_NAME&#125; -Dsonar.java.binaries=target/ -Dsonar.login=7d66af4b39cfe4f52ac0a915d4c9d5c513207098&#x27;</span> <br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;制作自定义镜像并发布Harbor&#x27;</span>) &#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">&#x27;cp ./target/*.jar ./docker/</span><br><span class="hljs-string">                cd ./docker</span><br><span class="hljs-string">                docker build -t $&#123;JOB_NAME&#125;:$&#123;tag&#125; ./&#x27;</span><span class="hljs-string">&#x27;&#x27;</span><br><br>                sh <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">&#x27;docker login -u $&#123;harborUser&#125; -p $&#123;harborPasswd&#125; $&#123;harborHost&#125;</span><br><span class="hljs-string">                docker tag $&#123;JOB_NAME&#125;:$&#123;tag&#125; $&#123;harborHost&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:$&#123;tag&#125;</span><br><span class="hljs-string">                docker push $&#123;harborHost&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:$&#123;tag&#125;&#x27;</span><span class="hljs-string">&#x27;&#x27;</span><br>            &#125;<br>        &#125;<br>        <br>        stage(<span class="hljs-string">&#x27;目标服务器拉取镜像并运行&#x27;</span>) &#123;<br>            steps &#123;<br>                sshPublisher(publishers: [sshPublisherDesc(configName: <span class="hljs-string">&#x27;testEnvironment&#x27;</span>, transfers: [sshTransfer(cleanRemote: <span class="hljs-literal">false</span>, excludes: <span class="hljs-string">&#x27;&#x27;</span>, execCommand: <span class="hljs-string">&quot;/usr/bin/deploy.sh <span class="hljs-variable">$harborHost</span> <span class="hljs-variable">$harborRepo</span> <span class="hljs-variable">$JOB_NAME</span> <span class="hljs-variable">$tag</span> <span class="hljs-variable">$port</span> &quot;</span>, execTimeout: 120000, flatten: <span class="hljs-literal">false</span>, makeEmptyDirs: <span class="hljs-literal">false</span>, noDefaultExcludes: <span class="hljs-literal">false</span>, patternSeparator: <span class="hljs-string">&#x27;[, ]+&#x27;</span>, remoteDirectory: <span class="hljs-string">&#x27;&#x27;</span>, remoteDirectorySDF: <span class="hljs-literal">false</span>, removePrefix: <span class="hljs-string">&#x27;&#x27;</span>, sourceFiles: <span class="hljs-string">&#x27;&#x27;</span>)], usePromotionTimestamp: <span class="hljs-literal">false</span>, useWorkspaceInPromotion: <span class="hljs-literal">false</span>, verbose: <span class="hljs-literal">false</span>)])<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ul>
<p><a href="">Ps：由于采用变量，记得使用双引号</a></p>
<h4 id="9-4-Jenkins流水线整合钉钉"><a href="#9-4-Jenkins流水线整合钉钉" class="headerlink" title="9.4 Jenkins流水线整合钉钉"></a>9.4 Jenkins流水线整合钉钉</h4><p>在程序部署成功后，可以通过钉钉的机器人及时向群众发送部署的最终结果通知</p>
<ul>
<li><p>安装插件</p>
<table>
<thead>
<tr>
<th align="center">安装插件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211209151549412.png" srcset="/img/loading.gif" lazyload alt="image-20211209151549412"></td>
</tr>
</tbody></table>
</li>
<li><p>钉钉内部创建群组并构建机器人</p>
<table>
<thead>
<tr>
<th align="center">钉钉内部创建群组并构建机器人</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211209152217433.png" srcset="/img/loading.gif" lazyload alt="image-20211209152217433"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211209152252050.png" srcset="/img/loading.gif" lazyload alt="image-20211209152252050"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211209152403312.png" srcset="/img/loading.gif" lazyload alt="image-20211209152403312"></td>
</tr>
</tbody></table>
<p>最终或获取到Webhook信息</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">https:<span class="hljs-regexp">//</span>oapi.dingtalk.com<span class="hljs-regexp">/robot/</span>send?access_token=kej4ehkj34gjhg34jh5bh5jb34hj53b4<br></code></pre></td></tr></table></figure>
</li>
<li><p>系统配置添加钉钉通知</p>
<table>
<thead>
<tr>
<th align="center">配置钉钉通知</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211209162923440.png" srcset="/img/loading.gif" lazyload alt="image-20211209162923440"></td>
</tr>
</tbody></table>
</li>
<li><p>任务中追加流水线配置</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><code class="hljs sh">pipeline &#123;<br>    agent any<br><br>    environment &#123;<br>        sonarLogin = <span class="hljs-string">&#x27;2bab7bf7d5af25e2c2ca2f178af2c3c55c64d5d8&#x27;</span><br>        harborUser = <span class="hljs-string">&#x27;admin&#x27;</span><br>        harborPassword = <span class="hljs-string">&#x27;Harbor12345&#x27;</span><br>        harborHost = <span class="hljs-string">&#x27;192.168.11.12:8888&#x27;</span><br>        harborRepo = <span class="hljs-string">&#x27;repository&#x27;</span><br>    &#125;<br><br>    stages &#123;<br>        stage(<span class="hljs-string">&#x27;拉取Git代码&#x27;</span>)&#123;<br>            steps &#123;<br>                checkout([<span class="hljs-variable">$class</span>: <span class="hljs-string">&#x27;GitSCM&#x27;</span>, branches: [[name: <span class="hljs-string">&#x27;$tag&#x27;</span>]], extensions: [], userRemoteConfigs: [[url: <span class="hljs-string">&#x27;http://49.233.115.171:8929/root/lsx.git&#x27;</span>]]])<br>            &#125;<br>        &#125;<br>        stage(<span class="hljs-string">&#x27;Maven构建代码&#x27;</span>)&#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/maven/bin/mvn clean package -DskipTests&#x27;</span><br>            &#125;<br>        &#125;<br>        stage(<span class="hljs-string">&#x27;SonarQube检测代码&#x27;</span>)&#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=$&#123;JOB_NAME&#125; -Dsonar.projectKey=$&#123;JOB_NAME&#125; -Dsonar.java.binaries=target/ -Dsonar.login=$&#123;sonarLogin&#125;&#x27;</span><br>            &#125;<br>        &#125;<br>        stage(<span class="hljs-string">&#x27;制作自定义镜像&#x27;</span>)&#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">&#x27;cd docker</span><br><span class="hljs-string">                mv ../target/*.jar ./</span><br><span class="hljs-string">                docker build -t $&#123;JOB_NAME&#125;:$tag .</span><br><span class="hljs-string">                &#x27;</span><span class="hljs-string">&#x27;&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;推送自定义镜像&#x27;</span>)&#123;<br>            steps &#123;<br>                sh <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">&#x27;docker login -u $&#123;harborUser&#125; -p $&#123;harborPassword&#125; $&#123;harborHost&#125;</span><br><span class="hljs-string">                docker tag $&#123;JOB_NAME&#125;:$tag $&#123;harborHost&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:$tag</span><br><span class="hljs-string">                docker push $&#123;harborHost&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:$tag&#x27;</span><span class="hljs-string">&#x27;&#x27;</span><br>            &#125;<br>        &#125;<br><br>        stage(<span class="hljs-string">&#x27;通知目标服务器&#x27;</span>)&#123;<br>            steps &#123;<br>                sshPublisher(publishers: [sshPublisherDesc(configName: <span class="hljs-string">&#x27;centos-docker&#x27;</span>, transfers: [sshTransfer(cleanRemote: <span class="hljs-literal">false</span>, excludes: <span class="hljs-string">&#x27;&#x27;</span>, execCommand: <span class="hljs-string">&quot;/usr/bin/deploy.sh <span class="hljs-variable">$harborHost</span> <span class="hljs-variable">$harborRepo</span> <span class="hljs-variable">$JOB_NAME</span> <span class="hljs-variable">$tag</span> <span class="hljs-variable">$port</span>&quot;</span>, execTimeout: 120000, flatten: <span class="hljs-literal">false</span>, makeEmptyDirs: <span class="hljs-literal">false</span>, noDefaultExcludes: <span class="hljs-literal">false</span>, patternSeparator: <span class="hljs-string">&#x27;[, ]+&#x27;</span>, remoteDirectory: <span class="hljs-string">&#x27;&#x27;</span>, remoteDirectorySDF: <span class="hljs-literal">false</span>, removePrefix: <span class="hljs-string">&#x27;&#x27;</span>, sourceFiles: <span class="hljs-string">&#x27;&#x27;</span>)], usePromotionTimestamp: <span class="hljs-literal">false</span>, useWorkspaceInPromotion: <span class="hljs-literal">false</span>, verbose: <span class="hljs-literal">false</span>)])<br>            &#125;  <br>        &#125;<br>    &#125;<br>    post &#123;<br>        success &#123;<br>            dingtalk (<br>                robot: <span class="hljs-string">&#x27;Jenkins-DingDing&#x27;</span>,<br>                <span class="hljs-built_in">type</span>:<span class="hljs-string">&#x27;MARKDOWN&#x27;</span>,<br>                title: <span class="hljs-string">&quot;success: <span class="hljs-variable">$&#123;JOB_NAME&#125;</span>&quot;</span>,<br>                text: [<span class="hljs-string">&quot;- 成功构建:<span class="hljs-variable">$&#123;JOB_NAME&#125;</span>项目!\n- 版本:<span class="hljs-variable">$&#123;tag&#125;</span>\n- 持续时间:<span class="hljs-variable">$&#123;currentBuild.durationString&#125;</span>\n- 任务:#<span class="hljs-variable">$&#123;JOB_NAME&#125;</span>&quot;</span>]<br>            )<br>        &#125;<br>        failure &#123;<br>            dingtalk (<br>                robot: <span class="hljs-string">&#x27;Jenkins-DingDing&#x27;</span>,<br>                <span class="hljs-built_in">type</span>:<span class="hljs-string">&#x27;MARKDOWN&#x27;</span>,<br>                title: <span class="hljs-string">&quot;fail: <span class="hljs-variable">$&#123;JOB_NAME&#125;</span>&quot;</span>,<br>                text: [<span class="hljs-string">&quot;- 失败构建:<span class="hljs-variable">$&#123;JOB_NAME&#125;</span>项目!\n- 版本:<span class="hljs-variable">$&#123;tag&#125;</span>\n- 持续时间:<span class="hljs-variable">$&#123;currentBuild.durationString&#125;</span>\n- 任务:#<span class="hljs-variable">$&#123;JOB_NAME&#125;</span>&quot;</span>]<br>            )<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
</li>
<li><p>查看效果</p>
<table>
<thead>
<tr>
<th align="center">钉钉通知效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211209163021396.png" srcset="/img/loading.gif" lazyload alt="image-20211209163021396"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>###十、Kubernetes编排工具</p>
<h4 id="10-1-Kubernetes介绍"><a href="#10-1-Kubernetes介绍" class="headerlink" title="10.1 Kubernetes介绍"></a>10.1 Kubernetes介绍</h4><p>Kubernetes是一个开源的，用于管理云平台中多个主机上的容器化的应用，Kubernetes的目标是让部署容器化的应用简单并且高效（powerful），Kubernetes提供了应用部署，规划，更新，维护的一种机制。</p>
<p>Kubernetes一个核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着，管理员可以加载一个微型服务，让规划器来找到合适的位置，同时，Kubernetes也系统提升工具以及人性化方面，让用户能够方便的部署自己的应用。</p>
<p>Kubernetes主要能帮助我们完成：</p>
<ul>
<li><p>服务发现和负载均衡</p>
<p>Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器，如果进入容器的流量很大， Kubernetes 可以负载均衡并分配网络流量，从而使部署稳定。</p>
</li>
<li><p>存储编排</p>
<p>Kubernetes 允许你自动挂载你选择的存储系统，比如本地存储，类似Docker的数据卷。</p>
</li>
<li><p>自动部署和回滚</p>
<p>你可以使用 Kubernetes 描述已部署容器的所需状态，它可以以受控的速率将实际状态 更改为期望状态。Kubernetes 会自动帮你根据情况部署创建新容器，并删除现有容器给新容器提供资源。</p>
</li>
<li><p>自动完成装箱计算</p>
<p>Kubernetes 允许你设置每个容器的资源，比如CPU和内存。</p>
</li>
<li><p>自我修复</p>
<p>Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的容器，并运行状况检查的容器。</p>
</li>
<li><p>秘钥与配置管理</p>
<p>Kubernetes 允许你存储和管理敏感信息，例如密码、OAuth 令牌和 ssh 密钥。你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置，也无需在堆栈配置中暴露密钥。</p>
</li>
</ul>
<h4 id="10-2-Kubernetes架构"><a href="#10-2-Kubernetes架构" class="headerlink" title="10.2 Kubernetes架构"></a>10.2 Kubernetes架构</h4><p>Kubernetes 搭建需要至少两个节点，一个Master负责管理，一个Slave搭建在工作服务器上负责分配。</p>
<table>
<thead>
<tr>
<th align="center">kubernetes架构</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211210114507638.png" srcset="/img/loading.gif" lazyload alt="image-20211210114507638"></td>
</tr>
</tbody></table>
<p>从图中可以看到各个组件的基本功能：</p>
<ul>
<li>API Server：作为K8s通讯的核心组件，K8s内部交互以及接收发送指令的组件。</li>
<li>controller-manager：作为K8s的核心组件，主要做资源调度，根据集群情况分配资源</li>
<li>etcd：一个key-value的数据库，存储存储集群的状态信息</li>
<li>scheduler：负责调度每个工作节点</li>
<li>cloud-controller-manager：负责调度其他云服务产品</li>
<li>kubelet：管理Pods上面的容器。</li>
<li>kube-proxy：负责处理其他Slave或客户端的请求。</li>
<li>Pod：可以理解为就是运行的容器</li>
</ul>
<h4 id="10-3-Kubernetes安装"><a href="#10-3-Kubernetes安装" class="headerlink" title="10.3 Kubernetes安装"></a>10.3 Kubernetes安装</h4><p>这里会采用<a target="_blank" rel="noopener" href="https://kuboard.cn/%E6%8F%90%E4%BE%9B%E7%9A%84%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85K8s%EF%BC%8C%E5%AE%89%E8%A3%85%E5%8D%95Master%E8%8A%82%E7%82%B9">https://kuboard.cn/提供的方式安装K8s，安装单Master节点</a></p>
<ul>
<li>要求使用Centos7.8版本：<a target="_blank" rel="noopener" href="https://vault.centos.org/7.8.2003/isos/x86_64/CentOS-7-x86_64-Minimal-2003.iso">https://vault.centos.org/7.8.2003/isos/x86_64/CentOS-7-x86_64-Minimal-2003.iso</a></li>
<li>至少2台 <strong>2核4G</strong> 的服务器</li>
</ul>
<p>安装流程</p>
<table>
<thead>
<tr>
<th align="center">安装流程</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211210190653687.png" srcset="/img/loading.gif" lazyload alt="image-20211210190653687"></td>
</tr>
</tbody></table>
<p>准备好服务器后开始安装</p>
<ul>
<li><p>重新设置hostname，不允许为localhost</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 修改 hostname，名字不允许使用下划线、小数点、大写字母，不能叫master</span><br>hostnamectl set-hostname your-new-host-name<br><span class="hljs-comment"># 查看修改结果</span><br>hostnamectl status<br><span class="hljs-comment"># 设置 hostname 解析</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;127.0.0.1   <span class="hljs-subst">$(hostname)</span>&quot;</span> &gt;&gt; /etc/hosts<br></code></pre></td></tr></table></figure>
</li>
<li><p>要求2台服务之间可以相互通讯</p>
</li>
<li><p>安装软件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 阿里云 docker hub 镜像</span><br><span class="hljs-built_in">export</span> REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com<br>curl -sSL https://kuboard.cn/install-script/v1.19.x/install_kubelet.sh | sh -s 1.19.5<br></code></pre></td></tr></table></figure></li>
</ul>
<p>首先初始化Master节点</p>
<blockquote>
<p>关于初始化时用到的环境变量</p>
<ul>
<li><strong>APISERVER_NAME</strong> 不能是 master 的 hostname</li>
<li><strong>APISERVER_NAME</strong> 必须全为小写字母、数字、小数点，不能包含减号</li>
<li><strong>POD_SUBNET</strong> 所使用的网段不能与 <em><strong>master节点&#x2F;worker节点</strong></em> 所在的网段重叠。该字段的取值为一个 <a target="_blank" rel="noopener" href="https://kuboard.cn/glossary/cidr.html">CIDR</a> 值，如果您对 CIDR 这个概念还不熟悉，请仍然执行 export POD_SUBNET&#x3D;10.100.0.0&#x2F;16 命令，不做修改</li>
</ul>
</blockquote>
<ul>
<li><p>设置ip，域名，网段并执行初始化操作</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 只在 master 节点执行</span><br><span class="hljs-comment"># 替换 x.x.x.x 为 master 节点实际 IP（请使用内网 IP）</span><br><span class="hljs-comment"># export 命令只在当前 shell 会话中有效，开启新的 shell 窗口后，如果要继续安装过程，请重新执行此处的 export 命令</span><br><span class="hljs-built_in">export</span> MASTER_IP=192.168.11.32<br><span class="hljs-comment"># 替换 apiserver.demo 为 您想要的 dnsName</span><br><span class="hljs-built_in">export</span> APISERVER_NAME=apiserver.demo<br><span class="hljs-comment"># Kubernetes 容器组所在的网段，该网段安装完成后，由 kubernetes 创建，事先并不存在于您的物理网络中</span><br><span class="hljs-built_in">export</span> POD_SUBNET=10.100.0.1/16<br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;<span class="hljs-variable">$&#123;MASTER_IP&#125;</span>    <span class="hljs-variable">$&#123;APISERVER_NAME&#125;</span>&quot;</span> &gt;&gt; /etc/hosts<br>curl -sSL https://kuboard.cn/install-script/v1.19.x/init_master.sh | sh -s 1.19.5<br></code></pre></td></tr></table></figure>
</li>
<li><p>检查Master启动状态</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 只在 master 节点执行</span><br><br><span class="hljs-comment"># 执行如下命令，等待 3-10 分钟，直到所有的容器组处于 Running 状态</span><br>watch kubectl get pod -n kube-system -o wide<br><br><span class="hljs-comment"># 查看 master 节点初始化结果</span><br>kubectl get nodes -o wide<br></code></pre></td></tr></table></figure></li>
</ul>
<p><code>Ps：如果出现NotReady的情况执行（最新版本的BUG，1.19一般没有）</code></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker pull quay.io/coreos/flannel:v0.10.0-amd64 <br><span class="hljs-built_in">mkdir</span> -p /etc/cni/net.d/<br><span class="hljs-built_in">cat</span> &lt;&lt;<span class="hljs-string">EOF&gt; /etc/cni/net.d/10-flannel.conf</span><br><span class="hljs-string">&#123;&quot;name&quot;:&quot;cbr0&quot;,&quot;type&quot;:&quot;flannel&quot;,&quot;delegate&quot;: &#123;&quot;isDefaultGateway&quot;: true&#125;&#125;</span><br><span class="hljs-string">EOF</span><br><span class="hljs-built_in">mkdir</span> /usr/share/oci-umount/oci-umount.d -p<br><span class="hljs-built_in">mkdir</span> /run/flannel/<br><span class="hljs-built_in">cat</span> &lt;&lt;<span class="hljs-string">EOF&gt; /run/flannel/subnet.env</span><br><span class="hljs-string">FLANNEL_NETWORK=172.100.0.0/16</span><br><span class="hljs-string">FLANNEL_SUBNET=172.100.1.0/24</span><br><span class="hljs-string">FLANNEL_MTU=1450</span><br><span class="hljs-string">FLANNEL_IPMASQ=true</span><br><span class="hljs-string">EOF</span><br>kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml<br></code></pre></td></tr></table></figure>

<p>安装网络服务插件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-built_in">export</span> POD_SUBNET=10.100.0.0/16<br>kubectl apply -f https://kuboard.cn/install-script/v1.22.x/calico-operator.yaml<br>wget https://kuboard.cn/install-script/v1.22.x/calico-custom-resources.yaml<br>sed -i <span class="hljs-string">&quot;s#192.168.0.0/16#<span class="hljs-variable">$&#123;POD_SUBNET&#125;</span>#&quot;</span> calico-custom-resources.yaml<br>kubectl apply -f calico-custom-resources.yaml<br></code></pre></td></tr></table></figure>

<p>初始化worker节点</p>
<ul>
<li><p>获取Join命令参数，在Master节点执行</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 只在 master 节点执行</span><br>kubeadm token create --print-join-command<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">获取命令</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211213183025291.png" srcset="/img/loading.gif" lazyload alt="image-20211213183025291"></td>
</tr>
</tbody></table>
</li>
<li><p>在worker节点初始化</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 只在 worker 节点执行</span><br><span class="hljs-comment"># 替换 x.x.x.x 为 master 节点的内网 IP</span><br><span class="hljs-built_in">export</span> MASTER_IP=192.168.11.32<br><span class="hljs-comment"># 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME</span><br><span class="hljs-built_in">export</span> APISERVER_NAME=apiserver.demo<br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;<span class="hljs-variable">$&#123;MASTER_IP&#125;</span>    <span class="hljs-variable">$&#123;APISERVER_NAME&#125;</span>&quot;</span> &gt;&gt; /etc/hosts<br><br><span class="hljs-comment"># 替换为 master 节点上 kubeadm token create 命令的输出</span><br>kubeadm <span class="hljs-built_in">join</span> apiserver.demo:6443 --token vwfilu.3nhndohc5gn1jv9k     --discovery-token-ca-cert-hash sha256:22ff15cabfe87ab48a7db39b3bbf986fee92ec92eb8efc7fe9b0abe2175ff0c2<br></code></pre></td></tr></table></figure></li>
</ul>
<p>检查最终运行效果</p>
<ul>
<li><p>在 master 节点上执行</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 只在 master 节点执行</span><br>kubectl get nodes -o wide<br></code></pre></td></tr></table></figure></li>
</ul>
<p><code>Ps：如果出现NotReady的情况执行（最新版本的BUG，1.19一般没有）</code></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs sh">docker pull quay.io/coreos/flannel:v0.10.0-amd64 <br><span class="hljs-built_in">mkdir</span> -p /etc/cni/net.d/<br><span class="hljs-built_in">cat</span> &lt;&lt;<span class="hljs-string">EOF&gt; /etc/cni/net.d/10-flannel.conf</span><br><span class="hljs-string">&#123;&quot;name&quot;:&quot;cbr0&quot;,&quot;type&quot;:&quot;flannel&quot;,&quot;delegate&quot;: &#123;&quot;isDefaultGateway&quot;: true&#125;&#125;</span><br><span class="hljs-string">EOF</span><br><span class="hljs-built_in">mkdir</span> /usr/share/oci-umount/oci-umount.d -p<br><span class="hljs-built_in">mkdir</span> /run/flannel/<br><span class="hljs-built_in">cat</span> &lt;&lt;<span class="hljs-string">EOF&gt; /run/flannel/subnet.env</span><br><span class="hljs-string">FLANNEL_NETWORK=172.100.0.0/16</span><br><span class="hljs-string">FLANNEL_SUBNET=172.100.1.0/24</span><br><span class="hljs-string">FLANNEL_MTU=1450</span><br><span class="hljs-string">FLANNEL_IPMASQ=true</span><br><span class="hljs-string">EOF</span><br>kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml<br></code></pre></td></tr></table></figure>

<ul>
<li><p>输出结果如下所示：</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sh">[root@k8smaster ~]<span class="hljs-comment"># kubectl get nodes</span><br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">搭建成功效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211210184851810.png" srcset="/img/loading.gif" lazyload alt="image-20211210184851810"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>安装Kuboard管理K8s集群</p>
<ul>
<li><p>安装Kuboard</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-string">kubectl</span> <span class="hljs-string">apply</span> <span class="hljs-string">-f</span> <span class="hljs-string">https://addons.kuboard.cn/kuboard/kuboard-v3.yaml</span><br><span class="hljs-comment"># 您也可以使用下面的指令，唯一的区别是，该指令使用华为云的镜像仓库替代 docker hub 分发 Kuboard 所需要的镜像</span><br><span class="hljs-comment"># kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3-swr.yaml</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>查看启动情况</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">watch kubectl <span class="hljs-built_in">get</span> pods -n kuboard<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">查看效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211213184701784.png" srcset="/img/loading.gif" lazyload alt="image-20211213184701784"></td>
</tr>
</tbody></table>
</li>
<li><p>在浏览器中打开链接 <a target="_blank" rel="noopener" href="http://your-node-ip-address:30080/">http://your-node-ip-address:30080</a></p>
<table>
<thead>
<tr>
<th align="center">首页</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211213184742709.png" srcset="/img/loading.gif" lazyload alt="image-20211213184742709"></td>
</tr>
</tbody></table>
</li>
<li><p>输入初始用户名和密码，并登录</p>
<ul>
<li>用户名： <code>admin</code></li>
<li>密码： <code>Kuboard123</code></li>
</ul>
<table>
<thead>
<tr>
<th align="center">首页效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20211213184840120.png" srcset="/img/loading.gif" lazyload alt="image-20211213184840120"></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="10-4-Kubernetes操作"><a href="#10-4-Kubernetes操作" class="headerlink" title="10.4 Kubernetes操作"></a>10.4 Kubernetes操作</h4><p>首先我们要了解Kubernetes在运行我们的资源时，关联到了哪些内容</p>
<ul>
<li><p>资源的构建方式：</p>
<ul>
<li>采用kubectl的命令方式</li>
<li>yaml文件方式</li>
</ul>
</li>
</ul>
<h5 id="10-4-1-Namespace"><a href="#10-4-1-Namespace" class="headerlink" title="10.4.1 Namespace"></a>10.4.1 Namespace</h5><ul>
<li><p>命名空间：主要是为了对Kubernetes中运行的资源进行过隔离， 但是网络是互通的，类似Docker的容器，可以将多个资源配置到一个NameSpace中。而NameSpace可以对不同环境进行资源隔离，默认情况下Kubernetes提供了default命名空间，在构建资源时，如果不指定资源，默认采用default资源。<br>命令方式：</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 查看现有的全部命名空间</span><br>kubectl get ns<br><br><span class="hljs-comment"># 构建命名空间</span><br>kubectl create ns 命名空间名称<br><br><span class="hljs-comment"># 删除现有命名空间， 并且会删除空间下的全部资源</span><br>kubectl delete ns 命名空间名称<br></code></pre></td></tr></table></figure>

<p>yaml文件方式：（构建资源时，设置命名空间）</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Namespace</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">test</span><br></code></pre></td></tr></table></figure></li>
</ul>
<h5 id="10-4-2-Pod"><a href="#10-4-2-Pod" class="headerlink" title="10.4.2 Pod"></a>10.4.2 Pod</h5><ul>
<li><p>Pod：Kubernetes运行的一组容器，Pod是Kubernetes的最小单位，但是对于Docker而然，Pod中会运行多个Docker容器</p>
<ul>
<li><p>命令方式：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看所有运行的pod</span><br>kubectl get pods -A<br><br><span class="hljs-comment"># 查看指定Namespace下的Pod</span><br>kubectl get pod [-n 命名空间]  <span class="hljs-comment">#（默认default）</span><br><br><span class="hljs-comment"># 创建Pod</span><br>kubectl run pod名称 --image=镜像名称<br><br><span class="hljs-comment"># 查看Pod详细信息</span><br>kubectl describe pod pod名称<br><br><span class="hljs-comment"># 删除pod</span><br>kubectl delete pod pod名称 [-n 命名空间]  <span class="hljs-comment">#（默认default）</span><br><br><span class="hljs-comment"># 查看pod输出的日志</span><br>kubectl logs -f pod名称<br><br><span class="hljs-comment"># 进去pod容器内部</span><br>kubectl <span class="hljs-built_in">exec</span> -it pod名称 -- bash<br><br><span class="hljs-comment"># 查看kubernetes给Pod分配的ip信息，并且通过ip和容器的端口，可以直接访问</span><br>kubectl get pod -owide<br></code></pre></td></tr></table></figure>
</li>
<li><p>yaml方式（推荐）</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">run:</span> <span class="hljs-string">运行的pod名称</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">pod名称</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">命名空间</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">containers:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">镜像名称</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">容器名称</span><br><br><span class="hljs-comment"># 启动Pod：kubectl apply -f yaml文件名称</span><br><span class="hljs-comment"># 删除Pod：kubectl delete -f yaml文件名称</span><br></code></pre></td></tr></table></figure>
</li>
<li><p>Pod中运行多个容器</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">run:</span> <span class="hljs-string">运行的pod名称</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">pod名称</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">命名空间</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">containers:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">镜像名称</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">容器名称</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">镜像名称</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">容器名称</span><br><span class="hljs-string">…………</span>    <br></code></pre></td></tr></table></figure>

<p>启动后可以查看到</p>
<table>
<thead>
<tr>
<th align="center">Kuboard效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220104203155749.png" srcset="/img/loading.gif" lazyload alt="image-20220104203155749"></td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
<h5 id="10-4-3-Deployment"><a href="#10-4-3-Deployment" class="headerlink" title="10.4.3 Deployment"></a>10.4.3 Deployment</h5><p>部署时，可以通过Deployment管理和编排Pod</p>
<p>Deployment部署实现</p>
<ul>
<li><p>命令方式</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 基于Deployment启动容器</span><br>kubectl create deployment deployment名称 --image=镜像名称<br><span class="hljs-comment"># 用deployment启动的容器会在被删除后自动再次创建，达到故障漂移的效果</span><br><span class="hljs-comment"># 需要使用deploy的方式删除deploy</span><br><span class="hljs-comment"># 查看现在的deployment</span><br>kubectl get deployment<br><br><span class="hljs-comment"># 删除deployment</span><br>kubectl delete deployment deployment名称<br><br><span class="hljs-comment"># 基于Deployment启动容器并设置Pod集群数</span><br>kubectl create deployment deployment名称 --image=镜像名称 --replicas 集群个数<br></code></pre></td></tr></table></figure>
</li>
<li><p><a target="_blank" rel="noopener" href="https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/">配置文件方式</a></p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-deployment</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">matchLabels:</span><br>      <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span><br>  <span class="hljs-attr">template:</span><br>    <span class="hljs-attr">metadata:</span><br>      <span class="hljs-attr">labels:</span><br>        <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span><br>    <span class="hljs-attr">spec:</span><br>      <span class="hljs-attr">containers:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span><br>       <span class="hljs-attr">image:</span> <span class="hljs-string">nginx</span><br>       <span class="hljs-attr">ports:</span><br>       <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span><br></code></pre></td></tr></table></figure>

<p>正常使用kubectl运行yaml即可</p>
</li>
</ul>
<p>弹性伸缩功能</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 基于scale实现弹性伸缩</span><br>kubectl scale deploy/Deployment名称 --replicas 集群个数<br><span class="hljs-comment"># 或者修改yaml文件</span><br>kubectl edit deploy Deployment名称<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">图形化页面修改</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220104210823057.png" srcset="/img/loading.gif" lazyload alt="image-20220104210823057"></td>
</tr>
</tbody></table>
<p>灰度发布</p>
<p>Deploy可以在部署新版本数据时，成功启动一个pod，才会下线一个老版本的Pod</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">kubectl set image deployment/Deployment名称 容器名=镜像:版本<br></code></pre></td></tr></table></figure>

<h5 id="10-4-4-Service"><a href="#10-4-4-Service" class="headerlink" title="10.4.4 Service"></a>10.4.4 Service</h5><p>可以将多个Pod对外暴露一个Service，让客户端可以通过Service访问到这一组Pod，并且可以实现负载均衡</p>
<p>ClusterIP方式：</p>
<p>ClusterIP是集群内部Pod之间的访问方式</p>
<ul>
<li><p>命令实现效果</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器</span><br>kubectl expose deployment Deployment名称 --port=Service端口号 --target-port=Pod内容器端口<br></code></pre></td></tr></table></figure>

<p>之后通过<code>kubectl get service</code>查看Service提供的ip，即可访问</p>
<table>
<thead>
<tr>
<th align="center">kubectl get service</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220104214659229.png" srcset="/img/loading.gif" lazyload alt="image-20220104214659229"></td>
</tr>
</tbody></table>
<p>也可以通过<code>Deployment名称.namespace名称.svc</code>作为域名访问</p>
<table>
<thead>
<tr>
<th align="center">在服务容器内执行</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220104215030265.png" srcset="/img/loading.gif" lazyload alt="image-20220104215030265"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>NodePort方式</p>
<p>ClusterIP的方式只能在Pod内部实现访问，但是一般需要对外暴露网关，所以需要NodePort的方式Pod外暴露访问</p>
<ul>
<li><p>命令实现方式</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器</span><br>kubectl expose deployment Deployment名称 --port=Service端口号 --target-port=Pod内容器端口 --<span class="hljs-built_in">type</span>=NodePort<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">查看Service效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220104222750733.png" srcset="/img/loading.gif" lazyload alt="image-20220104222750733"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220104222819455.png" srcset="/img/loading.gif" lazyload alt="image-20220104222819455"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>Service也可以通过yaml文件实现</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-string">labels</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span><br>  <span class="hljs-attr">spec:</span><br>    <span class="hljs-attr">selector:</span><br>      <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span><br>    <span class="hljs-attr">ports:</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">8888</span><br>     <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span><br>     <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span><br></code></pre></td></tr></table></figure>

<p>通过apply启动就也可以创建Service</p>
<p>测试效果-Deployment部署，通过Service暴露</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-deployment</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-deployment</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">replicas:</span> <span class="hljs-number">2</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">matchLabels:</span><br>      <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-deployment</span><br>  <span class="hljs-attr">template:</span><br>    <span class="hljs-attr">metadata:</span><br>      <span class="hljs-attr">labels:</span><br>        <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-deployment</span><br>    <span class="hljs-attr">spec:</span><br>      <span class="hljs-attr">containers:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-deployment</span><br>        <span class="hljs-attr">image:</span> <span class="hljs-string">nginx</span><br>        <span class="hljs-attr">ports:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span><br><span class="hljs-meta">---</span><br><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-service</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-service</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-deployment</span><br>  <span class="hljs-attr">ports:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">8888</span><br>    <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span><br>    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span><br>  <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span><br></code></pre></td></tr></table></figure>

<p>可以查看到暴露的信息</p>
<table>
<thead>
<tr>
<th align="center">Service信息</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105205334996.png" srcset="/img/loading.gif" lazyload alt="image-20220105205334996"></td>
</tr>
</tbody></table>
<h5 id="10-4-5-Ingress"><a href="#10-4-5-Ingress" class="headerlink" title="10.4.5 Ingress"></a>10.4.5 Ingress</h5><p>Kubernetes推荐将Ingress作为所有Service的入口，提供统一的入口，避免多个服务之间需要记录大量的IP或者域名，毕竟IP可能改变，服务太多域名记录不方便。</p>
<p>Ingress底层其实就是一个Nginx， 可以在Kuboard上直接点击安装</p>
<table>
<thead>
<tr>
<th align="center">Kuboard安装</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105153343642.png" srcset="/img/loading.gif" lazyload alt="image-20220105153343642"></td>
</tr>
<tr>
<td align="center"><strong><img src="/../images/DevOps/Pictures/image-20220105153416367.png" srcset="/img/loading.gif" lazyload alt="image-20220105153416367"></strong></td>
</tr>
</tbody></table>
<p>因为副本数默认为1，但是k8s整体集群就2个节点，所以显示下面即为安装成功</p>
<table>
<thead>
<tr>
<th align="center">安装成功</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105153502619.png" srcset="/img/loading.gif" lazyload alt="image-20220105153502619"></td>
</tr>
</tbody></table>
<p>可以将Ingress接收到的请求转发到不同的Service中。</p>
<p>推荐使用yaml文件方式</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.k8s.io/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Ingress</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-ingress</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">ingressClassName:</span> <span class="hljs-string">ingress</span><br>  <span class="hljs-attr">rules:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">host:</span> <span class="hljs-string">nginx.mashibing.com</span><br>    <span class="hljs-attr">http:</span><br>      <span class="hljs-attr">paths:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">path:</span> <span class="hljs-string">/</span><br>        <span class="hljs-attr">pathType:</span> <span class="hljs-string">Prefix</span><br>        <span class="hljs-attr">backend:</span><br>          <span class="hljs-attr">service:</span><br>            <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-service</span><br>            <span class="hljs-attr">port:</span><br>              <span class="hljs-attr">number:</span> <span class="hljs-number">8888</span><br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">启动时问题</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105203819715.png" srcset="/img/loading.gif" lazyload alt="image-20220105203819715"></td>
</tr>
</tbody></table>
<p>Kuboard安装的Ingress有admission的校验配置，需要先删除配置再启动</p>
<p>找到指定的ingress的校验信息，删除即可</p>
<table>
<thead>
<tr>
<th align="center">删除信息</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105204434044.png" srcset="/img/loading.gif" lazyload alt="image-20220105204434044"></td>
</tr>
</tbody></table>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sh"><span class="hljs-comment"># 查看校验webhook的配置</span><br>kubectl get -A ValidatingWebhookConfiguration<br><br><span class="hljs-comment"># 删除指定的校验</span><br>kubectl delete ValidatingWebhookConfiguration ingress-nginx-admission-my-ingress-controller<br></code></pre></td></tr></table></figure>

<p>配置本地hosts文件</p>
<table>
<thead>
<tr>
<th align="center">配置hosts</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105204921272.png" srcset="/img/loading.gif" lazyload alt="image-20220105204921272"></td>
</tr>
</tbody></table>
<p>记下来既可以访问在Service中暴露的Nginx信息</p>
<table>
<thead>
<tr>
<th align="center">服通过Ingress访问</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/image-20220105205407393.png" srcset="/img/loading.gif" lazyload alt="image-20220105205407393"></td>
</tr>
</tbody></table>
<h4 id="10-5-Jenkins集成Kubernetes"><a href="#10-5-Jenkins集成Kubernetes" class="headerlink" title="10.5 Jenkins集成Kubernetes"></a>10.5 Jenkins集成Kubernetes</h4><h5 id="10-5-1-准备部署的yml文件"><a href="#10-5-1-准备部署的yml文件" class="headerlink" title="10.5.1 准备部署的yml文件"></a>10.5.1 准备部署的yml文件</h5><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">test</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">replicas:</span> <span class="hljs-number">2</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">matchLabels:</span><br>      <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span><br>  <span class="hljs-attr">template:</span><br>    <span class="hljs-attr">metadata:</span><br>      <span class="hljs-attr">labels:</span><br>        <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span>    <br>    <span class="hljs-attr">spec:</span><br>      <span class="hljs-attr">containers:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span><br>        <span class="hljs-attr">image:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.11</span><span class="hljs-number">.102</span><span class="hljs-string">:80/repo/pipeline:v4.0.0</span><br>        <span class="hljs-attr">imagePullPolicy:</span> <span class="hljs-string">Always</span><br>        <span class="hljs-attr">ports:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">8080</span><br><span class="hljs-meta">---</span><br><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">test</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span>  <br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span><br>  <span class="hljs-attr">ports:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">8081</span><br>    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">8080</span><br>  <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span><br><span class="hljs-meta">---</span><br><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.k8s.io/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Ingress</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">test</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">ingressClassName:</span> <span class="hljs-string">ingress</span><br>  <span class="hljs-attr">rules:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">host:</span> <span class="hljs-string">mashibing.pipeline.com</span><br>    <span class="hljs-attr">http:</span><br>      <span class="hljs-attr">paths:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">path:</span> <span class="hljs-string">/</span><br>        <span class="hljs-attr">pathType:</span> <span class="hljs-string">Prefix</span><br>        <span class="hljs-attr">backend:</span><br>          <span class="hljs-attr">service:</span><br>            <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span><br>            <span class="hljs-attr">port:</span><br>              <span class="hljs-attr">number:</span> <span class="hljs-number">8081</span><br></code></pre></td></tr></table></figure>



<h5 id="10-5-2-Harbor私服配置"><a href="#10-5-2-Harbor私服配置" class="headerlink" title="10.5.2 Harbor私服配置"></a>10.5.2 Harbor私服配置</h5><p>在尝试用kubernetes的yml文件启动pipeline服务时，会出现Kubernetes无法拉取镜像的问题，这里需要在kubernetes所在的Linux中配置Harbor服务信息，并且保证Kubernetes可以拉取Harbor上的镜像</p>
<ul>
<li><p>设置Master和Worker的私服地址信息</p>
<table>
<thead>
<tr>
<th align="center">设置Harbor私服地址</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642498962716.png" srcset="/img/loading.gif" lazyload alt="1642498962716"></td>
</tr>
</tbody></table>
</li>
<li><p>在Kuboard上设置私服密文信息</p>
<table>
<thead>
<tr>
<th align="center">设置密文并测试</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642498994935.png" srcset="/img/loading.gif" lazyload alt="1642498994935"></td>
</tr>
</tbody></table>
<p>按照复制指令的位置测试认证，效果如下</p>
<table>
<thead>
<tr>
<th align="center">测试效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642499172789.png" srcset="/img/loading.gif" lazyload alt="1642499172789"></td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="10-5-3-测试使用效果"><a href="#10-5-3-测试使用效果" class="headerlink" title="10.5.3 测试使用效果"></a>10.5.3 测试使用效果</h5><p>执行kubectl命令，基于yml启动服务，并且基于部署后服务的提示信息以及Ingress的设置，直接访问</p>
<table>
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody><tr>
<td><img src="/../images/DevOps/Pictures/1642499368121.png" srcset="/img/loading.gif" lazyload alt="1642499368121"></td>
</tr>
<tr>
<td><img src="/../images/DevOps/Pictures/1642499788199.png" srcset="/img/loading.gif" lazyload alt="1642499788199"></td>
</tr>
</tbody></table>
<h5 id="10-5-3-Jenkins远程调用"><a href="#10-5-3-Jenkins远程调用" class="headerlink" title="10.5.3 Jenkins远程调用"></a>10.5.3 Jenkins远程调用</h5><ul>
<li><p>将pipeline.yml配置到Gitlab中</p>
<table>
<thead>
<tr>
<th align="center">配置yml文件</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642499885324.png" srcset="/img/loading.gif" lazyload alt="1642499885324"></td>
</tr>
</tbody></table>
</li>
<li><p>配置Jenkins的目标服务器，可以将yml文件传输到K8s的Master上</p>
<table>
<thead>
<tr>
<th align="center">设置目标服务器</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642499992148.png" srcset="/img/loading.gif" lazyload alt="1642499992148"></td>
</tr>
</tbody></table>
</li>
<li><p>修改Jenkinsfile，重新设置流水线任务脚本，并测试效果</p>
<table>
<thead>
<tr>
<th align="center">传递yml文件脚本</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500061153.png" srcset="/img/loading.gif" lazyload alt="1642500061153"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500102996.png" srcset="/img/loading.gif" lazyload alt="1642500102996"></td>
</tr>
</tbody></table>
</li>
<li><p>设置Jenkins无密码登录k8s-master</p>
<p>将Jenkins中公钥信息复制到k8s-master的~&#x2F;.ssh&#x2F;authorized_keysz中，保证远程连接无密码</p>
<table>
<thead>
<tr>
<th align="center">远程执行命令无需密码</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500239406.png" srcset="/img/loading.gif" lazyload alt="1642500239406"></td>
</tr>
</tbody></table>
</li>
<li><p>设置执行kubectl的脚本到Jenkinsfile</p>
<table>
<thead>
<tr>
<th align="center">设置Jenkinsfile</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500378788.png" srcset="/img/loading.gif" lazyload alt="1642500378788"></td>
</tr>
</tbody></table>
</li>
<li><p>执行查看效果</p>
<table>
<thead>
<tr>
<th align="center">执行流水线</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500413802.png" srcset="/img/loading.gif" lazyload alt="1642500413802"></td>
</tr>
</tbody></table>
<p>可以查看到yml文件是由变化的， 这样k8s就会重新加载</p>
</li>
<li><p>查看效果</p>
<table>
<thead>
<tr>
<th align="center">效果</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500474036.png" srcset="/img/loading.gif" lazyload alt="1642500474036"></td>
</tr>
</tbody></table>
</li>
</ul>
<p><a href="">Ps：这种方式更适应与CD操作，将项目将基于某个版本部署到指定的目标服务器</a></p>
<h4 id="10-6-基于GitLab的WebHooks"><a href="#10-6-基于GitLab的WebHooks" class="headerlink" title="10.6 基于GitLab的WebHooks"></a>10.6 基于GitLab的WebHooks</h4><p>这里要实现自动化的一个CI操作，也就是开发人员Push代码到Git仓库后，Jenkins会自动的构建项目，将最新的提交点代码构建并进行打包部署，这里区别去上述的CD操作，CD操作需要基于某个版本进行部署，而这里每次都是将最新的提交点集成到主干上并测试。</p>
<h5 id="10-6-1-WebHooks通知"><a href="#10-6-1-WebHooks通知" class="headerlink" title="10.6.1 WebHooks通知"></a>10.6.1 WebHooks通知</h5><p>开启Jenkins的自动构建</p>
<table>
<thead>
<tr>
<th align="center">构建触发器</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500817131.png" srcset="/img/loading.gif" lazyload alt="1642500817131"></td>
</tr>
</tbody></table>
<p>设置Gitlab的Webhooks</p>
<table>
<thead>
<tr>
<th align="center">设置Gitlab的Webhooks</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642500933316.png" srcset="/img/loading.gif" lazyload alt="1642500933316"></td>
</tr>
</tbody></table>
<p>需要关闭Jenkins的Gitlab认证</p>
<table>
<thead>
<tr>
<th align="center">关闭Jenkins的Gitlab认证</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642501016474.png" srcset="/img/loading.gif" lazyload alt="1642501016474"></td>
</tr>
</tbody></table>
<p>再次测试Gitlab</p>
<table>
<thead>
<tr>
<th align="center">再次测试</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642501065243.png" srcset="/img/loading.gif" lazyload alt="1642501065243"></td>
</tr>
</tbody></table>
<h5 id="10-6-2-修改配置"><a href="#10-6-2-修改配置" class="headerlink" title="10.6.2 修改配置"></a>10.6.2 修改配置</h5><p>修改Jenkinsfile实现基于最新提交点实现持续集成效果，将之前引用${tag}的全部去掉</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-comment">// 所有的脚本命令都放在pipeline中</span><br>pipeline<span class="hljs-punctuation">&#123;</span><br>	<span class="hljs-comment">// 指定任务再哪个集群节点中执行</span><br>	agent any<br><br>	<span class="hljs-comment">// 声明全局变量，方便后面使用</span><br>	environment <span class="hljs-punctuation">&#123;</span><br>		harborUser = &#x27;admin&#x27;<br>        harborPasswd = &#x27;Harbor12345&#x27;<br>        harborAddress = &#x27;<span class="hljs-number">192.168</span><span class="hljs-number">.11</span><span class="hljs-number">.102</span><span class="hljs-punctuation">:</span><span class="hljs-number">80</span>&#x27;<br>        harborRepo = &#x27;repo&#x27;<br>	<span class="hljs-punctuation">&#125;</span><br><br>    stages <span class="hljs-punctuation">&#123;</span><br>        stage(&#x27;拉取git仓库代码&#x27;) <span class="hljs-punctuation">&#123;</span><br>            steps <span class="hljs-punctuation">&#123;</span><br>                checkout(<span class="hljs-punctuation">[</span>$class<span class="hljs-punctuation">:</span> &#x27;GitSCM&#x27;<span class="hljs-punctuation">,</span> branches<span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">[</span>name<span class="hljs-punctuation">:</span> &#x27;*/master&#x27;<span class="hljs-punctuation">]</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> extensions<span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> userRemoteConfigs<span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">[</span>url<span class="hljs-punctuation">:</span> &#x27;http<span class="hljs-punctuation">:</span><span class="hljs-comment">//192.168.11.101:8929/root/mytest.git&#x27;]]])</span><br>            <span class="hljs-punctuation">&#125;</span><br>        <span class="hljs-punctuation">&#125;</span><br>        stage(&#x27;通过maven构建项目&#x27;) <span class="hljs-punctuation">&#123;</span><br>            steps <span class="hljs-punctuation">&#123;</span><br>                sh &#x27;/var/jenkins_home/maven/bin/mvn clean package -DskipTests&#x27;<br>            <span class="hljs-punctuation">&#125;</span><br>        <span class="hljs-punctuation">&#125;</span><br>        stage(&#x27;通过SonarQube做代码质量检测&#x27;) <span class="hljs-punctuation">&#123;</span><br>            steps <span class="hljs-punctuation">&#123;</span><br>                sh &#x27;/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.source=./ -Dsonar.projectname=$<span class="hljs-punctuation">&#123;</span>JOB_NAME<span class="hljs-punctuation">&#125;</span> -Dsonar.projectKey=$<span class="hljs-punctuation">&#123;</span>JOB_NAME<span class="hljs-punctuation">&#125;</span> -Dsonar.java.binaries=./target/ -Dsonar.login=<span class="hljs-number">40306</span>ae8ea69a4792df2ceb4d9d25fe8a6ab1701&#x27;<br>            <span class="hljs-punctuation">&#125;</span><br>        <span class="hljs-punctuation">&#125;</span><br>        stage(&#x27;通过Docker制作自定义镜像&#x27;) <span class="hljs-punctuation">&#123;</span><br>            steps <span class="hljs-punctuation">&#123;</span><br>                sh &#x27;&#x27;&#x27;mv ./target<span class="hljs-comment">/*.jar ./docker/</span><br><span class="hljs-comment">                docker build -t $&#123;JOB_NAME&#125;:latest ./docker/&#x27;&#x27;&#x27;</span><br><span class="hljs-comment">            &#125;</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment">        stage(&#x27;将自定义镜像推送到Harbor&#x27;) &#123;</span><br><span class="hljs-comment">            steps &#123;</span><br><span class="hljs-comment">                sh &#x27;&#x27;&#x27;docker login -u $&#123;harborUser&#125; -p $&#123;harborPasswd&#125; $&#123;harborAddress&#125;</span><br><span class="hljs-comment">                docker tag $&#123;JOB_NAME&#125;:latest  $&#123;harborAddress&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:latest</span><br><span class="hljs-comment">                docker push $&#123;harborAddress&#125;/$&#123;harborRepo&#125;/$&#123;JOB_NAME&#125;:latest &#x27;&#x27;&#x27;</span><br><span class="hljs-comment">            &#125;</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment">        stage(&#x27;将yml文件传到k8s-master上&#x27;) &#123;</span><br><span class="hljs-comment">            steps &#123;</span><br><span class="hljs-comment">                sshPublisher(publishers: [sshPublisherDesc(configName: &#x27;k8s&#x27;, transfers: [sshTransfer(cleanRemote: false, excludes: &#x27;&#x27;, execCommand: &#x27;&#x27;, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: &#x27;[, ]+&#x27;, remoteDirectory: &#x27;&#x27;, remoteDirectorySDF: false, removePrefix: &#x27;&#x27;, sourceFiles: &#x27;pipeline.yml&#x27;)], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])</span><br><span class="hljs-comment">            &#125;</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment">        stage(&#x27;远程执行k8s-master的kubectl命令&#x27;) &#123;</span><br><span class="hljs-comment">            steps &#123;</span><br><span class="hljs-comment">               sh &#x27;&#x27;&#x27;ssh root@192.168.11.201 kubectl apply -f /usr/local/k8s/pipeline.yml</span><br><span class="hljs-comment">                ssh root@192.168.11.201 kubectl rollout restart deployment pipeline -n test&#x27;&#x27;&#x27;</span><br><span class="hljs-comment">            &#125;</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">    &#125;</span><br><span class="hljs-comment">    post &#123;</span><br><span class="hljs-comment">        success &#123;</span><br><span class="hljs-comment">            dingtalk(</span><br><span class="hljs-comment">                robot: &#x27;Jenkins-DingDing&#x27;,</span><br><span class="hljs-comment">                type: &#x27;MARKDOWN&#x27;,</span><br><span class="hljs-comment">                title: &quot;success: $&#123;JOB_NAME&#125;&quot;,</span><br><span class="hljs-comment">                text: [&quot;- 成功构建：$&#123;JOB_NAME&#125;! \n- 版本：latest \n- 持续时间：$&#123;currentBuild.durationString&#125;&quot; ]</span><br><span class="hljs-comment">            )</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment">        failure &#123;</span><br><span class="hljs-comment">            dingtalk(</span><br><span class="hljs-comment">                robot: &#x27;Jenkins-DingDing&#x27;,</span><br><span class="hljs-comment">                type: &#x27;MARKDOWN&#x27;,</span><br><span class="hljs-comment">                title: &quot;success: $&#123;JOB_NAME&#125;&quot;,</span><br><span class="hljs-comment">                text: [&quot;- 构建失败：$&#123;JOB_NAME&#125;! \n- 版本：latest \n- 持续时间：$&#123;currentBuild.durationString&#125;&quot; ]</span><br><span class="hljs-comment">            )</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment">    &#125;</span><br><span class="hljs-comment">&#125;</span><br><span class="hljs-comment"></span><br></code></pre></td></tr></table></figure>

<p>修改pipeline.yml，更改镜像版本</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs yml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">test</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">replicas:</span> <span class="hljs-number">2</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">matchLabels:</span><br>      <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span><br>  <span class="hljs-attr">template:</span><br>    <span class="hljs-attr">metadata:</span><br>      <span class="hljs-attr">labels:</span><br>        <span class="hljs-attr">app:</span> <span class="hljs-string">pipeline</span>    <br>    <span class="hljs-attr">spec:</span><br>      <span class="hljs-attr">containers:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">pipeline</span><br>        <span class="hljs-attr">image:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.11</span><span class="hljs-number">.102</span><span class="hljs-string">:80/repo/pipeline:latest</span>   <span class="hljs-comment"># 这里</span><br>        <span class="hljs-attr">imagePullPolicy:</span> <span class="hljs-string">Always</span><br>        <span class="hljs-attr">ports:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">8080</span><br><span class="hljs-comment"># 省略其他内容…………</span><br></code></pre></td></tr></table></figure>

<h5 id="10-6-3-滚动更新"><a href="#10-6-3-滚动更新" class="headerlink" title="10.6.3 滚动更新"></a>10.6.3 滚动更新</h5><p>因为pipeline没有改变时，每次不会重新加载，这样会导致Pod中的容器不会动态更新，这里需要使用kubectl的rollout restart命令滚动更新</p>
<table>
<thead>
<tr>
<th align="center">设置Jenkinsfle</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642501521065.png" srcset="/img/loading.gif" lazyload alt="1642501521065"></td>
</tr>
<tr>
<td align="center"><img src="/../images/DevOps/Pictures/1642501549176.png" srcset="/img/loading.gif" lazyload alt="1642501549176"></td>
</tr>
</tbody></table>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/devops/" class="category-chain-item">devops</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/devops/">#devops</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>DevOps</div>
      <div>http://example.com/2023/06/11/DevOps/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>c5p1ng</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2023年6月11日</div>
        </div>
      
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2023/06/11/%E5%9F%BA%E4%BA%8ENacos%E5%AE%9E%E7%8E%B0%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1/" title="基于Nacos实现动态路由">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">基于Nacos实现动态路由</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2023/05/27/hexo%E4%BD%BF%E7%94%A8/" title="hexo使用">
                        <span class="hidden-mobile">hexo使用</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="busuanzi_container_site_pv" style="display: none">
        总访问量 
        <span id="busuanzi_value_site_pv"></span>
         次
      </span>
    
    
      <span id="busuanzi_container_site_uv" style="display: none">
        总访客数 
        <span id="busuanzi_value_site_uv"></span>
         人
      </span>
    
    
  
</div>

  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
